Skip to content

docs: clarify gcloud release upload permissions - #14

Open
ibetitsmike wants to merge 2 commits into
mainfrom
mike/fix-release-upload
Open

ibetitsmike wants to merge 2 commits into
mainfrom
mike/fix-release-upload

Conversation

@ibetitsmike

@ibetitsmike ibetitsmike commented Sep 11, 2026

Copy link
Copy Markdown

Why

Use gcloud storage cp as requested in the review discussion, rather than maintaining direct curl uploads. The original failure was caused by missing bucket-list permission. coder/gcp#233 adds the reader binding as a follow-up to coder/gcp#229.

Changes

  • Revert the curl implementation and restore the upload workflow byte-for-byte to main: standard Google auth/setup actions, generation-zero preconditions, full checksum-manifest verification, and a separate SHA256SUMS upload after payloads succeed.
  • Document unconditional bucket-level roles/storage.objectViewer access alongside the existing prefix-scoped roles/storage.objectCreator binding.
  • State the permission tradeoff: reads/listing cover the whole bucket; writes stay under mutagen/, with no delete permission. Public access is unchanged.

Because main already uses gcloud, this PR's net diff is now documentation only. Apply coder/gcp#233 before the next promotion. A failed gcloud batch can leave some payloads uploaded, but the manifest is withheld; the documented operator cleanup remains necessary.

Validation

  • Workflow equality with origin/main verified by Git blob hash.
  • Actionlint, Bash syntax, full ShellCheck with GitHub Actions errexit semantics, and diff checks passed.
  • Seven localhost tests ran the actual upload shell with gcloud SDK 575.0.1 and small synthetic payloads. Coverage: successful uploads with byte equality, build-metadata tags, denied listing, existing-object refusal, partial failures withholding the manifest, and generation/order red controls.
  • Companion GCP change passed Terraform formatting and validation without backend access. Its successful CI plan contains one in-place IAM policy update: 0 to add, 1 to change, 0 to destroy.
  • Push CI and PR CI passed on this exact head: 11 successful checks and 3 expected skips, none failed or pending.

Delivery record

  • Current head: 114c024f6aa1ab95bb7bae67d45b7d7b11bc5a32. No history rewrite. DCO-signed and locally verified SSH signature; GitHub reports unknown_key, as it did for the previous head.
  • Independent advisory: Xum task 87aa6c1fd0 reviewed the exact source blobs now committed in this head (workflow aaeb657; release docs 744a3b4) and the companion GCP diff. No material findings or deferred code issues. The seven-test pass was completed after that advisory.
  • Earlier advisory on 262ba17 and the successful live v0.18.4 promotion covered the superseded curl implementation only. They do not validate the new gcloud/IAM path.
  • Human review: the original request to use gcloud is implemented. The follow-up reply links the IAM fix. The reviewer thread remains open for confirmation, not treated as approval.
  • Live IAM/service-account upload on this head: not run. No Terraform apply, IAM changes, promotion, merge, or new release was performed. Live validation is blocked until the companion IAM change is applied; human review and separate merge authorization remain required.

Xum updated this PR on behalf of @ibetitsmike.

Use direct authenticated object PUTs instead of gcloud cp, which probes
new destinations with a bucket listing. Preserve generation-zero
preconditions, verify transport MD5, and upload the manifest last.

> Xum prepared this change on behalf of @ibetitsmike.

Signed-off-by: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com>
@ibetitsmike ibetitsmike changed the title mike/fix release upload ci: upload release objects without listing the bucket Sep 11, 2026
@ibetitsmike
ibetitsmike marked this pull request as ready for review September 11, 2026 12:38
Comment thread .github/workflows/upload-release.yml Outdated
Comment on lines +64 to +74
for artifact in artifacts/mutagen-* artifacts/SHA256SUMS; do
content_md5="$(openssl dgst -md5 -binary "$artifact" | openssl base64 -A)"
curl --fail-with-body --silent --show-error \
--header "Authorization: Bearer $GCLOUD_ACCESS_TOKEN" \
--header "Content-Type: application/octet-stream" \
--header "x-goog-if-generation-match: 0" \
--header "Content-MD5: $content_md5" \
--upload-file "$artifact" \
"https://storage.googleapis.com/coder-desktop/mutagen/$RELEASE_TAG/${artifact##*/}"
printf 'Uploaded gs://coder-desktop/mutagen/%s/%s\n' "$RELEASE_TAG" "${artifact##*/}"
done

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why? I'd so much rather use gcloud here

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’d prefer gcloud too if we can preserve the same permissions. The original live run failed on storage.objects.list before uploading anything.

The SDK 575.0.1 localhost reproduction noted under this PR’s Validation section also tried an exact destination name with --if-generation-match=0: object GET → 404 → bucket LIST with a prefix filter. The SDK treats a missing exact name as a possible directory. --no-clobber does not bypass that destination-discovery path according to source inspection; the saved probe used the generation precondition, so I’m not claiming a separately recorded --no-clobber run.

The uploader intentionally has create-only permission scoped to mutagen/. Bucket listing is not restricted by that object-prefix condition, so granting it would broaden access. Direct named-object PUT avoids discovery, with generation zero preventing overwrites, Content-MD5 validating transfer integrity, and SHA256SUMS last. The existing eight local tests cover those safeguards and failure paths; the live run on this head succeeded, and all six public downloads matched GitHub byte-for-byte.

Happy to switch back with a demonstrated list-free invocation, or a separately authorized IAM design change.

Xum replied on behalf of @ibetitsmike.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can, but we need to expand the gcp scope to be able to list the bucket (cli needs it to make sure there are no duplicates)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Restored gcloud storage cp in 114c024f and opened coder/gcp#233 for the missing bucket read/list permissions. The workflow is now identical to main, so this PR's net diff is the permissions documentation.

The IAM follow-up adds Mutagen-only bucket-level roles/storage.objectViewer, keeps writes restricted to mutagen/, and leaves public access and delete permissions unchanged. Generation-zero overwrite protection and manifest-last ordering remain. Local gcloud tests passed; no IAM apply or live promotion was run.

Leaving this thread open for your confirmation.

Xum replied on behalf of @ibetitsmike.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aslilac stamp plz

Signed-off-by: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com>
@ibetitsmike ibetitsmike changed the title ci: upload release objects without listing the bucket docs: clarify gcloud release upload permissions Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants