Skip to content
Latchkey

Build and Push to GHCR (Final) workflow (DR-lin-eng/stock-scanner)

The Build and Push to GHCR (Final) workflow from DR-lin-eng/stock-scanner, explained and optimized by Latchkey.

C

CI health: C - fair

Point runs-on at Latchkey and get run de-duplication, job timeouts, self-healing for flaky steps, and up to 58% lower cost, applied automatically.

Grade your own workflow free or run it on Latchkey →
Source: DR-lin-eng/stock-scanner.github/workflows/docker-build.ymlLicense MITView source

What it does

This is the Build and Push to GHCR (Final) workflow from the DR-lin-eng/stock-scanner repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.

Below, Latchkey shows a faster, safer version produced by its optimization engine.

The workflow

workflow (.yml)
name: Build and Push to GHCR (Final)
on:
  push:
    branches: [ main ]
    paths:
      - '3.0 webapp(支持港股美股)/**'
  workflow_dispatch:
jobs:
  build-and-push:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      packages: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          ref: ${{ github.ref }}
      
      - name: Set up Docker
        run: |
          sudo apt-get update
          sudo apt-get -f install
          sudo dpkg --configure -a
          sudo apt-get install -y ca-certificates curl gnupg
          sudo install -m 0755 -d /etc/apt/keyrings
          curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
          sudo chmod a+r /etc/apt/keyrings/docker.gpg
          echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
          sudo apt-get update
          sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
      
      - name: Set up QEMU for multi-architecture
        run: |
          sudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
      
      - name: Log in to GHCR
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | sudo docker login ghcr.io -u ${{ github.actor }} --password-stdin
      
      - name: Convert repository to lowercase
        run: |
          LOWERCASE_REPO=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]')
          echo "REPO_LOWER=$LOWERCASE_REPO" >> $GITHUB_ENV
      
      - name: Build AMD64 image
        run: |
          sudo docker build \
            --platform linux/amd64 \
            -f "2.6 webapp(流式传输测试版)/Dockerfile" \
            -t ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:2.6-amd64 \
            -t ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:latest-amd64 \
            "2.6 webapp(流式传输测试版)"
      
      - name: Build ARM64 image
        run: |
          sudo docker build \
            --platform linux/arm64 \
            -f "2.6 webapp(流式传输测试版)/Dockerfile" \
            -t ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:2.6-arm64 \
            -t ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:latest-arm64 \
            "2.6 webapp(流式传输测试版)"
      
      - name: Push individual architecture images
        run: |
          sudo docker push ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:2.6-amd64
          sudo docker push ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:latest-amd64
          sudo docker push ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:2.6-arm64
          sudo docker push ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:latest-arm64
      
      - name: Create and push multi-architecture manifest
        run: |
          # Create manifest for version 2.6
          sudo docker manifest create ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:2.6 \
            ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:2.6-amd64 \
            ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:2.6-arm64
          
          # Create manifest for latest
          sudo docker manifest create ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:latest \
            ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:latest-amd64 \
            ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:latest-arm64
          
          # Push manifests
          sudo docker manifest push ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:2.6
          sudo docker manifest push ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:latest
      
      - name: Add badge to README
        run: |
          # 创建临时分支
          git checkout -b update-readme-badge
          
          # 更新README
          if grep -q "ghcr-badge.deta.dev" README.md; then
            sed -i 's|!\[Docker Image\].*|![Docker Image](https://ghcr-badge.deta.dev/${{ env.REPO_LOWER }}/stock-webapp/latest_tag?trim=major\&label=最新版本)|' README.md
          else
            echo "![Docker Image](https://ghcr-badge.deta.dev/${{ env.REPO_LOWER }}/stock-webapp/latest_tag?trim=major\&label=最新版本)" >> README.md
          fi
          
          git config user.name "GitHub Actions"
          git config user.email "actions@users.noreply.github.com"
          git add README.md
          git commit -m "Update Docker image badge"
          
          # 推送到临时分支
          git push origin update-readme-badge
          
          # 创建PR
          gh pr create \
            --title "Update README with Docker badge" \
            --body "Automatically added Docker image badge to README" \
            --base main \
            --head update-readme-badge
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

The same workflow, on Latchkey

Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.

name: Build and Push to GHCR (Final)
on:
  push:
    branches: [ main ]
    paths:
      - '3.0 webapp(支持港股美股)/**'
  workflow_dispatch:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
 
jobs:
  build-and-push:
    timeout-minutes: 30
    runs-on: latchkey-small
    permissions:
      contents: write
      packages: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          ref: ${{ github.ref }}
      
      - name: Set up Docker
        run: |
          sudo apt-get update
          sudo apt-get -f install
          sudo dpkg --configure -a
          sudo apt-get install -y ca-certificates curl gnupg
          sudo install -m 0755 -d /etc/apt/keyrings
          curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
          sudo chmod a+r /etc/apt/keyrings/docker.gpg
          echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
          sudo apt-get update
          sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
      
      - name: Set up QEMU for multi-architecture
        run: |
          sudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
      
      - name: Log in to GHCR
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | sudo docker login ghcr.io -u ${{ github.actor }} --password-stdin
      
      - name: Convert repository to lowercase
        run: |
          LOWERCASE_REPO=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]')
          echo "REPO_LOWER=$LOWERCASE_REPO" >> $GITHUB_ENV
      
      - name: Build AMD64 image
        run: |
          sudo docker build \
            --platform linux/amd64 \
            -f "2.6 webapp(流式传输测试版)/Dockerfile" \
            -t ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:2.6-amd64 \
            -t ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:latest-amd64 \
            "2.6 webapp(流式传输测试版)"
      
      - name: Build ARM64 image
        run: |
          sudo docker build \
            --platform linux/arm64 \
            -f "2.6 webapp(流式传输测试版)/Dockerfile" \
            -t ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:2.6-arm64 \
            -t ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:latest-arm64 \
            "2.6 webapp(流式传输测试版)"
      
      - name: Push individual architecture images
        run: |
          sudo docker push ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:2.6-amd64
          sudo docker push ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:latest-amd64
          sudo docker push ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:2.6-arm64
          sudo docker push ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:latest-arm64
      
      - name: Create and push multi-architecture manifest
        run: |
          # Create manifest for version 2.6
          sudo docker manifest create ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:2.6 \
            ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:2.6-amd64 \
            ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:2.6-arm64
          
          # Create manifest for latest
          sudo docker manifest create ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:latest \
            ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:latest-amd64 \
            ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:latest-arm64
          
          # Push manifests
          sudo docker manifest push ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:2.6
          sudo docker manifest push ghcr.io/${{ env.REPO_LOWER }}/stock-webapp:latest
      
      - name: Add badge to README
        run: |
          # 创建临时分支
          git checkout -b update-readme-badge
          
          # 更新README
          if grep -q "ghcr-badge.deta.dev" README.md; then
            sed -i 's|!\[Docker Image\].*|![Docker Image](https://ghcr-badge.deta.dev/${{ env.REPO_LOWER }}/stock-webapp/latest_tag?trim=major\&label=最新版本)|' README.md
          else
            echo "![Docker Image](https://ghcr-badge.deta.dev/${{ env.REPO_LOWER }}/stock-webapp/latest_tag?trim=major\&label=最新版本)" >> README.md
          fi
          
          git config user.name "GitHub Actions"
          git config user.email "actions@users.noreply.github.com"
          git add README.md
          git commit -m "Update Docker image badge"
          
          # 推送到临时分支
          git push origin update-readme-badge
          
          # 创建PR
          gh pr create \
            --title "Update README with Docker badge" \
            --body "Automatically added Docker image badge to README" \
            --base main \
            --head update-readme-badge
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 

What changed

What Latchkey heals here

This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:

This workflow runs 1 job per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.

Actions used in this workflow