From 06ec0097f9668241742d0e981dcd4034e10e112d Mon Sep 17 00:00:00 2001 From: ginuerzh Date: Fri, 19 Jun 2026 19:11:25 +0800 Subject: [PATCH] ci: harden docker/release/nightly GitHub Actions workflows - buildx: adopt docker/metadata-action for image tags (replaces hand-rolled shell), add gha build cache, concurrency control, explicit checkout, and least-privilege permissions - release: add explicit permissions and concurrency (no cancel-in-flight); drop dead UPX install step (disabled in .goreleaser.yaml, see #863) - trigger-nightly: add concurrency, replace archived dev-drprasad/delete-older-releases with native gh, and harden the 24h commit check --- .github/workflows/buildx.yml | 69 +++++++++++++-------------- .github/workflows/release.yml | 14 +++--- .github/workflows/trigger-nightly.yml | 28 +++++++---- 3 files changed, 57 insertions(+), 54 deletions(-) diff --git a/.github/workflows/buildx.yml b/.github/workflows/buildx.yml index 1154009..fb0c502 100644 --- a/.github/workflows/buildx.yml +++ b/.github/workflows/buildx.yml @@ -3,57 +3,49 @@ name: docker -on: +on: push: branches: - master tags: - 'v*' +permissions: + contents: read + +# New pushes cancel an in-progress build for the same ref. Tags are isolated +# by ref, so re-pushing a release tag only de-dupes itself, never another tag. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: runs-on: ubuntu-latest steps: - - name: Prepare - id: prepare - run: | - DOCKER_IMAGE=${{ secrets.DOCKER_IMAGE }} - VERSION=latest + - name: Checkout + uses: actions/checkout@v4 - # If this is git tag, use the tag name as a docker tag - if [[ $GITHUB_REF == refs/tags/* ]]; then - VERSION=${GITHUB_REF#refs/tags/v} - fi - TAGS="${DOCKER_IMAGE}:${VERSION}" - - # If the VERSION looks like a version number, assume that - # this is the most recent version of the image and also - # tag it 'latest'. - if [[ $VERSION =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then - MAJOR_VERSION=`echo $VERSION | awk '{split($0,a,"."); print a[1]}'` - MINOR_VERSION=`echo $VERSION | awk '{split($0,a,"."); print a[2]}'` - TAGS="$TAGS,${DOCKER_IMAGE}:${MAJOR_VERSION},${DOCKER_IMAGE}:${MAJOR_VERSION}.${MINOR_VERSION},${DOCKER_IMAGE}:latest" - fi - - # Set output parameters. - echo "tags=${TAGS}" >> $GITHUB_OUTPUT - echo "docker_image=${DOCKER_IMAGE}" >> $GITHUB_OUTPUT - echo "docker_platforms=linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/s390x,linux/riscv64" >> $GITHUB_OUTPUT + # Auto-generates image tags, replacing the former hand-rolled shell: + # - master push -> :latest + # - clean release tag vX.Y.Z -> :X.Y.Z :X :X.Y :latest + # - nightly tag vX.Y.Z-nightly. -> :X.Y.Z-nightly. (no major/minor/latest) + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ secrets.DOCKER_IMAGE }} + flavor: latest=false + tags: | + type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) || (startsWith(github.ref, 'refs/tags/v') && !contains(github.ref_name, '-')) }} + type=semver,pattern={{version}} + type=semver,pattern={{major}},enable=${{ !contains(github.ref_name, '-') }} + type=semver,pattern={{major}}.{{minor}},enable=${{ !contains(github.ref_name, '-') }} - name: Set up Docker Buildx id: buildx uses: docker/setup-buildx-action@v3 - - name: Environment - run: | - echo home=$HOME - echo git_ref=$GITHUB_REF - echo git_sha=$GITHUB_SHA - echo image=${{ steps.prepare.outputs.docker_image }} - echo tags=${{ steps.prepare.outputs.tags }} - echo platforms=${{ steps.prepare.outputs.docker_platforms }} - echo avail_platforms=${{ steps.buildx.outputs.platforms }} - - name: Login to DockerHub if: github.event_name != 'pull_request' uses: docker/login-action@v3 @@ -64,6 +56,9 @@ jobs: - name: Buildx and push uses: docker/build-push-action@v6 with: - platforms: ${{ steps.prepare.outputs.docker_platforms }} + platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/s390x,linux/riscv64 push: true - tags: ${{ steps.prepare.outputs.tags }} \ No newline at end of file + tags: ${{ steps.meta.outputs.tags }} + # Reuse build layers across runs via the GitHub Actions cache. + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 99abff2..f0b33d4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,8 +8,11 @@ on: permissions: contents: write - # packages: write - # issues: write + +# Never cancel an in-flight release; only de-dupe a re-pushed tag. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false jobs: goreleaser: @@ -23,12 +26,7 @@ jobs: with: go-version: '1.26' cache: true - - name: Install UPX - uses: crazy-max/ghaction-upx@v3 - with: - install-only: true - # More assembly might be required: Docker logins, GPG, etc. It all depends - # on your needs. + # UPX is disabled in .goreleaser.yaml (see #863); the install step was removed. - uses: goreleaser/goreleaser-action@v6 with: # either 'goreleaser' (default) or 'goreleaser-pro': diff --git a/.github/workflows/trigger-nightly.yml b/.github/workflows/trigger-nightly.yml index 53bde40..81881b1 100644 --- a/.github/workflows/trigger-nightly.yml +++ b/.github/workflows/trigger-nightly.yml @@ -6,6 +6,11 @@ on: - cron: '00 15 * * *' workflow_dispatch: +# Only one nightly run at a time; a new run cancels a stale one. +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: true + jobs: check_date: runs-on: ubuntu-latest @@ -17,10 +22,12 @@ jobs: - name: print latest_commit run: echo ${{ github.sha }} - id: should_run - continue-on-error: true - name: check latest commit is less than a day + name: Skip if no commit in the last 24 hours if: ${{ github.event_name == 'schedule' }} - run: test -z $(git rev-list --after="24 hours" ${{ github.sha }}) && echo "should_run=false" >> $GITHUB_OUTPUT + run: | + if [ "$(git rev-list --count --after='24 hours' ${{ github.sha }})" -eq 0 ]; then + echo "should_run=false" >> $GITHUB_OUTPUT + fi trigger-nightly: needs: check_date @@ -52,10 +59,13 @@ jobs: git tag -a $TAG -m "$TAG: nightly build" git push origin $TAG - name: 'Clean up nightly releases' - uses: dev-drprasad/delete-older-releases@v0.3.3 - with: - keep_latest: 2 - delete_tags: true - delete_tag_pattern: nightly env: - GITHUB_TOKEN: ${{ secrets.NIGHTLY_BUILD_GH_TOKEN }} \ No newline at end of file + GH_TOKEN: ${{ secrets.NIGHTLY_BUILD_GH_TOKEN }} + run: | + # Keep the 2 most recent nightly releases; delete the rest and their tags. + # Replaces the archived dev-drprasad/delete-older-releases action. + gh release list --json tagName,createdAt --limit 100 \ + --jq '[.[] | select(.tagName | test("nightly"))] | sort_by(.createdAt) | reverse | .[2:] | .[].tagName' \ + | while read -r tag; do + gh release delete "$tag" --yes --cleanup-tag || true + done \ No newline at end of file