Skip to content

CD: deliver every signed release to Cloud Run and Firebase Hosting (T11) - #15

Merged
RyazanovAlexander merged 4 commits into
mainfrom
cd-terraform
Oct 14, 2026
Merged

RyazanovAlexander merged 4 commits into
mainfrom
cd-terraform

Conversation

@RyazanovAlexander

Copy link
Copy Markdown
Contributor

Summary

A green main now reaches prod without hands. release.yml ("Release and deploy") calls the new deploy.yml for a release that is still the newest commit of main. What goes out is exactly what the release signed: the server binary and the SPA archive, checked against SHA256SUMS. Its cosign signature must come from release.yml on main for the tag's commit.

Changes

  • deploy.yml:
    • target picks the release; a stale one gives a green run with a notice;
    • infra runs terraform apply in environment prod;
    • deploy builds the release image, rolls a revision by digest, sends it all traffic and smoke-tests /health, also in prod;
    • hosting runs firebase deploy and then checks the served page, in prod-hosting;
    • plan posts the plan in the PR's run summary.
  • Identity:
    • every service account is lent by the subject of its GitHub environment, and both environments allow main only;
    • a new canvas-api-hosting account publishes the SPA;
    • the Terraform identity gets projectIamAdmin, limited by an IAM condition to the publisher's two roles.
  • justfile: ci-release-target, ci-release-current, ci-release-fetch, ci-image-push, ci-deploy, ci-smoke, ci-hosting-deploy, ci-hosting-check, and a shared _image-health.
  • Dockerfile: a release stage that wraps the signed binary in the same distroless runtime.
  • firebase.json: no-cache on the page, immutable /assets/**, no rewrites.
  • Actions deployment-target, gcloud and firebase. The Firebase CLI 15.33.0 standalone binary is added to the devcontainer (x86_64).
  • Docs: R58 with amendments to R31, R45, R46 and R56; spec 15; docs/self-hosting.md (delivery, environments, rollback and return); SECURITY.md; README badge; stack; CLAUDE.md; RUN.md.

How it was verified

  • All required checks are green, and tf-check runs 16 tests.
  • actionlint and shellcheck report nothing new.
  • No cloud was used:
    • release v0.1.2 fetched and verified;
    • tampered files, a bundle of another file and another repository's signed release are all refused;
    • the release image was built and pushed to a local registry;
    • firebase.json and ci-hosting-check were checked on the Hosting emulator;
    • bootstrap ran against a stateful fake gcloud.
  • 18 checks were switched off one at a time to prove their tests, and each turned red.

Before merging

  • Environments prod and prod-hosting exist, with deployment branches limited to main.
  • Repository secret TF_VAR_billing_account is set.
  • just bootstrap has been re-run, and the Terraform identity is bound to :environment:prod and :pull_request only.
  • The plan job on this PR is green.

Merging this PR is the first delivery.

Open

  • Rollback and return are tested on the second delivery (T12).
  • Questions for the maintainer:
    • a read-only plan identity for PRs;
    • a no-traffic tagged rollout before shifting traffic;
    • actionlint in CI.

…e and deploy") calls the new `deploy.yml` for a release that is still the newest commit of `main`. What goes out is exactly what the release signed: the server binary and the SPA archive, checked against `SHA256SUMS`. Its cosign signature must come from `release.yml` on `main` for the tag's commit.
@sonarqubecloud

Copy link
Copy Markdown

@RyazanovAlexander
RyazanovAlexander merged commit 0bf1483 into main Oct 14, 2026
23 checks passed
@RyazanovAlexander
RyazanovAlexander deleted the cd-terraform branch October 14, 2026 18:31
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.

1 participant