← all branches

feat/tb-deploy

needs attentionviewing older commit
e81a781 · incrementalPR #261reviewed 2026-07-08 21:31 UTC0H · 4M · 4L · 1I
The branch
Purpose
Wire Batu's Tinybird deployment strategy: three long-lived workspaces (dev/stg/prod) with hard isolation, ephemeral Forward branches per PR, and per-environment token split
Goal
Automate what was done by hand: provision batu_stg + batu_prod, create least-privilege tokens, add schema-CD lanes, and seed all environments from per-env secrets
Sub-goals
  • SG-1: Strategy rule doc + README de-stale + scoped-runtime-vs-deploy-token split
  • SG-2: Per-env metrics-SSM seed (preview/staging/prod)
  • SG-3: Vercel per-env tokens
  • SG-4: Ephemeral per-PR Tinybird branch + cleanup
  • SG-5: Schema-CD — tinybird-staging / tinybird-prod jobs
  • SG-6: Fold per-env tokens + schema-CD into infrastructure.md / migration-pipeline.md
The changes (whole branch)
What
Added pinned composite action (.github/actions/tb-install) replacing curl|sh CLI installs across all 5 TB workflow jobs; added least-privilege permissions to tinybird-check, tinybird-staging, tinybird-prod, and deprovision jobs; wired tinybird-prod to run after cdk-deploy (expand/contract ordering); added tinybird-prod to rollback dependency graph; clarified SSM path convention in rule doc and branch cap in README.
Why
Eliminate the curl|sh supply-chain risk and add GITHUB_TOKEN least-privilege hardening as a follow-up to reviewer feedback on PR #261.
Areas
.github/actions+240.github/workflows+46949.claude/rules+2802infra/tinybird+11157
Blast
15 files total branch-wide (+929/-109); this increment: 8 files (+175/-51), all CI/infra and docs — zero application code changed
security-hardening ci-infra least-privilege-permissions supply-chain-pinning
ci-checks· GraphQL status check rollup not accessible with current token scopecoderabbit· No .coderabbit.yaml in repo

Findings · 9

security2

medium

PyPI package pinned by version only — no content hash

.github/actions/tb-install/action.yml:23

uv tool install 'tinybird==4.6.9' pins by version string but not by artifact hash. A tampered or yanked-then-republished PyPI wheel at this version could execute arbitrary code in jobs that hold TINYBIRD_DEPLOY_TOKEN_PROD and similar secrets. The astral-sh/setup-uv action is correctly pinned to a commit SHA, making this asymmetry notable. Fix: generate a hash pin via uv pip compile --generate-hashes and pass --hash sha256:<digest> to the install command.

low

Tinybird deploy failure now triggers full PITR DB rollback

.github/workflows/release-promote.yml:860

needs.tinybird-prod.result == 'failure' now triggers rollback including PITR DB restore. Tinybird schema changes are expand-only per the deployment rule doc, so a Tinybird deploy failure does not require DB rollback. A transient Tinybird API or network error could induce an unnecessary prod DB PITR restore of ~1-5 minutes. Consider separating Tinybird failure handling from the DB PITR trigger, or documenting this as an accepted trade-off.

conventions1

medium

tinybird-prod in rollback needs — no corresponding Tinybird rollback step

.github/workflows/release-promote.yml:856

The rollback job now lists tinybird-prod in its needs and fires when needs.tinybird-prod.result == 'failure'. However, the rollback job contains no tb command to revert a Tinybird schema deployment. It only handles CDK CloudFormation rollback, Vercel re-promotion, and DB PITR. This asymmetry misleads operators during an incident. Convention (matching db-backup): add an explicit comment noting that Tinybird schema rollback is intentionally unhandled here and describe the manual recovery path.

tests3

medium

Silent continue-on-error CLI install degradation is not surfaced

.github/workflows/preview-provision.yml:297

continue-on-error: true on the tb-install step in preview-provision and preview-deprovision means a broken uv install shows a green step while subsequent code falls through and exits 0 with a warning. The job appears fully green while the preview silently runs against the shared dev workspace. Add a job summary notice or a step output flag to make the degradation observable in the PR UI.

medium

No smoke-test workflow for the composite action

.github/actions/tb-install/action.yml

There is no workflow that directly exercises .github/actions/tb-install in isolation. Install failures only surface as buried failures inside provision/deprovision/staging runs rather than as fast, targeted signals. A PR-gated self-test (uses: ./.github/actions/tb-install then asserts tb --version) would prove the mechanism works as described.

low

No tb --version verification step in composite action

.github/actions/tb-install/action.yml

The action appends $HOME/.local/bin to GITHUB_PATH but does not run tb --version as a verification step. If uv places the binary at an unexpected location, the action exits 0 while tb is missing from PATH in subsequent steps.

improvement3

low

Branch slugification duplicated across provision and deprovision

.github/workflows/preview-deprovision.yml

The TB_SLUG derivation and BR convention appear identically in both preview-provision.yml and preview-deprovision.yml. If the two implementations drift, deprovision deletes the wrong branch and the 4-branch cap leaks. Extract to a shared composite action output, or store the computed branch name at provision time and read it back at deprovision time.

low

--force in uv tool install prevents cache reuse

.github/actions/tb-install/action.yml:23

--force causes uv to reinstall the tinybird tool even if the exact version is already present. If astral-sh/setup-uv's cache key ever covers the tool install directory, --force would negate it. Removing --force makes the install idempotent by default.

info

skip_cdk + tinybird ordering bypass undocumented

.github/workflows/release-promote.yml

tinybird-prod needs cdk-deploy enforces expand/contract ordering. However, if an operator passes skip_cdk: true but not skip_tinybird: true, GitHub Actions treats the skipped cdk-deploy as a satisfied dependency and tinybird-prod runs without the CDK gate. Documenting this in the dispatch input descriptions prevents a mis-invocation from violating the ordering invariant.

History · 10 commits

  1. 5d30429safeincremental0H · 0M · 1L2026-07-08 23:04
  2. 19bac85needs attentionincremental0H · 5M · 6L2026-07-08 22:46
  3. 92e890aneeds attentionincremental0H · 1M · 3L2026-07-08 21:46
  4. e81a781needs attentionincremental0H · 4M · 4L2026-07-08 21:31current
  5. 2eca91cneeds attentionfull5H · 13M · 12L2026-07-08 19:18
  6. cf63bb1needs attentionincremental4H · 4M · 7L2026-07-07 19:47
  7. f43d034needs attentionincremental2H · 3M · 3L2026-07-07 18:35
  8. b7800c0needs attentionincremental1H · 2M · 7L2026-07-07 03:31
  9. 5aef105needs attentionfull6H · 9M · 2L2026-07-06 17:52
  10. 95b4484blockedfull3H · 8M · 4L2026-07-06 05:36