From b30d87e25946da092681d5ae0e0019f07d6370e6 Mon Sep 17 00:00:00 2001 From: fOuttaMyPaint Date: Thu, 4 Jun 2026 20:33:40 -0400 Subject: [PATCH] ci: draft-then-publish releases to close the empty public window Previously create-release published an empty release immediately, leaving a 1-2 minute window where the public saw a partial release while the upload matrix attached assets. Now the release is created as a draft, the upload matrix attaches all 10 assets to the draft (still serialized so there is no create race), and a final publish-release job flips draft to false only after every asset is present. The release becomes public in one step with the full asset set. The upload-assets matrix sets draft: true explicitly because the action's draft input defaults to false and would otherwise publish the draft early on each update call. Preserves the 5 platform targets, asset names, 10 total assets, checksums, GITHUB_TOKEN, and contents: write only on the release-related jobs. Co-authored-by: Cursor --- .github/workflows/go.yml | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index e75a8b0..77e5947 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -50,6 +50,11 @@ jobs: # matrix below then only adds files to this already-existing release and can # never race to create it (the race that made action-gh-release v3 fail with # "already_exists (tag_name)"). + # + # The release is created as a draft so it is not publicly visible while the + # upload matrix is still attaching assets. The publish-release job flips it to + # published only after all assets are present, so the public never sees a + # partial or empty release. create-release: needs: build if: startsWith(github.ref, 'refs/tags/v') @@ -58,8 +63,10 @@ jobs: contents: write steps: - - name: Ensure release exists for tag + - name: Create draft release for tag uses: softprops/action-gh-release@v3 + with: + draft: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -137,12 +144,33 @@ jobs: # The release already exists (created by create-release), so each matrix leg # only adds its binary and checksum. No matrix job creates the release, which - # avoids the concurrent-create race entirely. - - name: Upload assets to release + # avoids the concurrent-create race entirely. draft: true is set explicitly + # so these update calls keep the release in draft (the action's draft input + # defaults to false and would otherwise publish it early). + - name: Upload assets to draft release uses: softprops/action-gh-release@v3 with: + draft: true files: | ${{ matrix.asset_name }} ${{ matrix.asset_name }}.sha256 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # Single job that publishes the release once, only after the full asset set is + # attached. Flipping draft to false here is the moment the release becomes + # public, so there is no window where a partial or empty release is visible. + publish-release: + needs: upload-assets + if: startsWith(github.ref, 'refs/tags/v') + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Publish release + uses: softprops/action-gh-release@v3 + with: + draft: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}