From 6add00559404cac579fe507f953dc3f125a20054 Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Thu, 10 Sep 2026 23:11:00 +0000 Subject: [PATCH 1/2] ci: add manual release upload to the Desktop bucket Download and verify an existing GitHub release before uploading its artifacts without overwriting published versions. Document the required bucket IAM grant for the existing workload identity. > Xum prepared this change on behalf of @ibetitsmike. Signed-off-by: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> --- .github/workflows/upload-release.yml | 66 ++++++++++++++++++++++++++++ RELEASING.md | 26 ++++++++--- 2 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/upload-release.yml diff --git a/.github/workflows/upload-release.yml b/.github/workflows/upload-release.yml new file mode 100644 index 00000000..aaeb6573 --- /dev/null +++ b/.github/workflows/upload-release.yml @@ -0,0 +1,66 @@ +name: Upload release + +on: + workflow_dispatch: + inputs: + tag: + description: 'Existing release tag (e.g. v0.18.4)' + required: true + type: string + +concurrency: + group: upload-release-${{ inputs.tag }} + cancel-in-progress: false + +jobs: + upload: + runs-on: ubuntu-latest + timeout-minutes: 15 + permissions: + contents: read + id-token: write + env: + RELEASE_TAG: ${{ inputs.tag }} + steps: + - name: Validate release tag + shell: bash + run: | + if [[ ! "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then + echo "Invalid release tag: $RELEASE_TAG" >&2 + exit 1 + fi + - uses: actions/checkout@v4 + with: + persist-credentials: false + - name: Download and verify release assets + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | + artifacts=( + mutagen-agents.tar.gz + mutagen-darwin-amd64 + mutagen-darwin-arm64 + mutagen-windows-amd64.exe + mutagen-windows-arm64.exe + ) + patterns=(--pattern SHA256SUMS) + for artifact in "${artifacts[@]}"; do + patterns+=(--pattern "$artifact") + done + gh release download "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" \ + --dir artifacts "${patterns[@]}" + cd artifacts + sha256sum "${artifacts[@]}" | diff - SHA256SUMS + - uses: google-github-actions/auth@v3 + with: + workload_identity_provider: ${{ vars.GCP_CODE_SIGNING_WORKLOAD_ID_PROVIDER }} + service_account: ${{ vars.GCP_CODE_SIGNING_SERVICE_ACCOUNT }} + - uses: google-github-actions/setup-gcloud@v3 + - name: Upload release assets + shell: bash + run: | + gcloud storage cp --if-generation-match=0 artifacts/mutagen-* \ + "gs://coder-desktop/mutagen/$RELEASE_TAG/" + gcloud storage cp --if-generation-match=0 artifacts/SHA256SUMS \ + "gs://coder-desktop/mutagen/$RELEASE_TAG/" diff --git a/RELEASING.md b/RELEASING.md index ca0600a8..1f75b7ad 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -23,12 +23,16 @@ Desktop. All of them are produced by the release with them attached. Running the workflow manually from the Actions tab builds the same artifacts from any ref and attaches them to the workflow run instead, which is useful for a dry run. -3. Copy the artifacts to the bucket that Coder Desktop reads from: +3. Run the [Upload release workflow](.github/workflows/upload-release.yml) + manually from the Actions tab, with the existing release tag (for example, + `v0.18.4`) as the `tag` input. It downloads the five release payloads and + `SHA256SUMS`, verifies the complete checksum manifest, and uploads the files + to `gs://coder-desktop/mutagen//` without rebuilding or re-signing them. + The bucket permissions described below must be in place first. - ```bash - gh release download v0.18.4 -R coder/mutagen -p 'mutagen-*' -D mutagen-v0.18.4 - gsutil cp mutagen-v0.18.4/* gs://coder-desktop/mutagen/v0.18.4/ - ``` + Uploads refuse to overwrite existing objects. Re-running a successful + upload fails; after a partial failure, an operator must inspect and remove + the partial upload before retrying. 4. Bump the Mutagen version in Coder Desktop: `$mutagenVersion` in `scripts/Get-Mutagen.ps1` (coder/coder-desktop-windows) and @@ -60,3 +64,15 @@ Federation. It needs the following repository configuration: The service account, its Cloud KMS roles, and its workload identity binding for this repository are managed in coder/gcp under `projects/production/coder-ci`. + +## Upload setup + +The upload workflow reuses the signing workflow's Workload Identity Federation +variables and service account. In addition to its signing permissions, the +account needs `roles/storage.objectCreator` on the `coder-desktop` bucket, +with an IAM condition limiting writes to objects whose resource name starts +with `projects/_/buckets/coder-desktop/objects/mutagen/`. + +The existing signing setup does not grant bucket access. Add this binding in +coder/gcp before running the upload workflow. No service account key or new +GitHub secret is needed. From 8f033ce8049b1e57354e91150edec3a7da70e710 Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Fri, 11 Sep 2026 05:37:25 +0000 Subject: [PATCH 2/2] docs: clarify existing Desktop bucket management Signed-off-by: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> --- RELEASING.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/RELEASING.md b/RELEASING.md index 1f75b7ad..d346e725 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -73,6 +73,8 @@ account needs `roles/storage.objectCreator` on the `coder-desktop` bucket, with an IAM condition limiting writes to objects whose resource name starts with `projects/_/buckets/coder-desktop/objects/mutagen/`. -The existing signing setup does not grant bucket access. Add this binding in -coder/gcp before running the upload workflow. No service account key or new -GitHub secret is needed. +The `coder-desktop` bucket already exists in project `coder-ci`. Its bucket +resource, IAM policy, and import declarations are managed in coder/gcp under +`projects/production/coder-ci`. Add the uploader binding to that existing +policy before running the upload workflow; do not create another bucket. +No service account key or new GitHub secret is needed.