Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions .github/workflows/upload-release.yml
Original file line number Diff line number Diff line change
@@ -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/"
28 changes: 23 additions & 5 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/<tag>/` 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
Expand Down Expand Up @@ -60,3 +64,17 @@ 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 `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.
Loading