From 5b9590e4d478ea573f4c297d7c63cb9eb320290d Mon Sep 17 00:00:00 2001 From: Grayson Adams <51373669+GraysonCAdams@users.noreply.github.com> Date: Sun, 1 Mar 2026 00:16:32 -0600 Subject: [PATCH] fix: simplify release workflow, remove GITHUB_TOKEN workarounds Strip out anti-patterns from the release workflow: - Remove fake status check injection via commit status API - Remove inline CodeQL job for release PRs - Remove inline Docker build job These were workarounds for GITHUB_TOKEN not triggering other workflows. The proper fix is a GitHub App token (documented in TODO comment). Restore docker-publish.yml with both release event trigger and manual workflow_dispatch fallback, with proper version extraction for release-please's scrolly-v* tag format. --- .github/workflows/docker-publish.yml | 29 +++-- .github/workflows/release.yml | 153 +++------------------------ 2 files changed, 38 insertions(+), 144 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 708ddea..1f6eeae 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -1,9 +1,13 @@ -name: Build & Publish Docker Image (Manual) +name: Build & Publish Docker Image -# Manual fallback for Docker publishing. -# Normally, Docker images are built automatically by the Release workflow. -# Use this workflow_dispatch if a release was created but the image wasn't published. on: + # Automatic trigger when a release is published. + # NOTE: This only works when releases are created with a GitHub App token + # (not GITHUB_TOKEN). Until the App is configured, use workflow_dispatch. + release: + types: [published] + + # Manual fallback for publishing when the release event doesn't fire. workflow_dispatch: inputs: version: @@ -32,6 +36,19 @@ jobs: - name: Checkout uses: actions/checkout@v4 + - name: Determine version + id: version + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + echo "version=${{ inputs.version }}" >> "$GITHUB_OUTPUT" + else + # Extract version from release tag (e.g. scrolly-v1.2.0 -> 1.2.0, v1.2.0 -> 1.2.0) + TAG="${{ github.event.release.tag_name }}" + VERSION="${TAG#scrolly-v}" + VERSION="${VERSION#v}" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + fi + - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -51,7 +68,7 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | - type=raw,value=${{ inputs.version }} + type=raw,value=${{ steps.version.outputs.version }} type=raw,value=latest - name: Build and push @@ -63,7 +80,7 @@ jobs: tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} build-args: | - APP_VERSION=${{ inputs.version }} + APP_VERSION=${{ steps.version.outputs.version }} cache-from: type=gha cache-to: type=gha,mode=max diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 409ec1a..04fb3bc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,154 +4,31 @@ on: push: branches: [main] +# TODO: Replace GITHUB_TOKEN with a GitHub App token to properly trigger +# CI/Security workflows on release-please PRs and docker-publish on releases. +# See: https://github.com/actions/create-github-app-token +# +# Once configured, add to this workflow: +# - name: Generate GitHub App token +# id: app-token +# uses: actions/create-github-app-token@v2 +# with: +# app-id: ${{ vars.RELEASE_APP_ID }} +# private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }} +# +# Then pass `token: ${{ steps.app-token.outputs.token }}` to release-please. +# This eliminates all workarounds for GITHUB_TOKEN event limitations. + permissions: contents: write pull-requests: write - statuses: write - packages: write - security-events: write jobs: release-please: runs-on: ubuntu-latest - outputs: - release_created: ${{ steps.release.outputs.release_created }} - tag_name: ${{ steps.release.outputs.tag_name }} - version: ${{ steps.release.outputs.version }} steps: - name: Run release-please - id: release uses: googleapis/release-please-action@v4 with: config-file: release-please-config.json manifest-file: .release-please-manifest.json - - # GITHUB_TOKEN-created PRs don't trigger CI workflows, so required - # status checks never run on the release branch. Since release-please - # only bumps versions and changelogs (code is already tested on main), - # we satisfy the required checks via the commit status API, then - # enable auto-merge so the PR merges once checks are satisfied. - - name: Auto-satisfy checks and enable auto-merge on release PR - if: steps.release.outputs.prs_created == 'true' - run: | - PR_NUMBER=$(gh pr list --label "autorelease: pending" --json number --jq '.[0].number') - if [ -z "$PR_NUMBER" ]; then - echo "No pending release PR found" - exit 0 - fi - echo "Found release PR #$PR_NUMBER" - SHA=$(gh pr view "$PR_NUMBER" --json headRefOid --jq '.headRefOid') - for check in ci security-status; do - gh api "repos/${{ github.repository }}/statuses/$SHA" \ - -f state=success \ - -f context="$check" \ - -f description="Release PR — code already tested on main" - done - gh pr merge "$PR_NUMBER" --squash --auto - env: - GH_TOKEN: ${{ github.token }} - - # Run CodeQL on the release PR branch to satisfy the code scanning ruleset. - # GITHUB_TOKEN-created PRs don't trigger other workflows, so we run CodeQL - # here to ensure results are uploaded for the release PR commit. - codeql-release-pr: - needs: release-please - if: needs.release-please.outputs.release_created != 'true' - runs-on: ubuntu-latest - timeout-minutes: 15 - steps: - - name: Find release PR - id: find-pr - run: | - PR_NUMBER=$(gh pr list --label "autorelease: pending" --json number --jq '.[0].number') - if [ -z "$PR_NUMBER" ]; then - echo "skip=true" >> "$GITHUB_OUTPUT" - exit 0 - fi - REF=$(gh pr view "$PR_NUMBER" --json headRefName --jq '.headRefName') - echo "ref=$REF" >> "$GITHUB_OUTPUT" - echo "skip=false" >> "$GITHUB_OUTPUT" - env: - GH_TOKEN: ${{ github.token }} - - - name: Checkout release PR branch - if: steps.find-pr.outputs.skip != 'true' - uses: actions/checkout@v4 - with: - ref: ${{ steps.find-pr.outputs.ref }} - - - name: Initialize CodeQL - if: steps.find-pr.outputs.skip != 'true' - uses: github/codeql-action/init@v3 - with: - languages: javascript-typescript - config-file: .github/codeql/codeql-config.yml - queries: security-extended - - - name: Autobuild - if: steps.find-pr.outputs.skip != 'true' - uses: github/codeql-action/autobuild@v3 - - - name: Perform CodeQL analysis - if: steps.find-pr.outputs.skip != 'true' - uses: github/codeql-action/analyze@v3 - with: - category: '/language:javascript-typescript' - - # Build and publish Docker image when a release is created. - # This runs in the same workflow to avoid the GITHUB_TOKEN limitation - # where release events created by GITHUB_TOKEN don't trigger other workflows. - docker: - needs: release-please - if: needs.release-please.outputs.release_created == 'true' - runs-on: ubuntu-latest - timeout-minutes: 20 - env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to GHCR - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=raw,value=${{ needs.release-please.outputs.version }} - type=raw,value=latest - - - name: Build and push - uses: docker/build-push-action@v6 - with: - context: . - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - build-args: | - APP_VERSION=${{ needs.release-please.outputs.version }} - cache-from: type=gha - cache-to: type=gha,mode=max - - - name: Set package visibility to public - run: | - curl -sf -X PATCH \ - -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ - -H "Accept: application/vnd.github.v3+json" \ - "https://api.github.com/orgs/312-dev/packages/container/scrolly" \ - -d '{"visibility":"public"}' || true