Workflow Gatekeeping
Every major workflow can be disabled centrally throughtuturuuu.ts.
The reusable workflow
ci-check.yml
reads that config and emits should_run, which downstream jobs use before doing
real work.
For Vercel deployments, ci-check.yml also performs affected-app gating before
any install, build, or deploy step starts. It checks the current GitHub event’s
changed files against Vercel app metadata and workspace dependency closures from
tuturuuu.ts.
The changed-file resolver must evaluate the full effective change range:
- Manual
workflow_dispatchruns bypass affected-app gating when the workflow is enabled. - Vercel production push workflows first look for the latest successful GitHub
Deployment marker for the same workflow and branch, then diff that marker SHA
to the current
GITHUB_SHA. - If no marker is available, push events use the GitHub event payload’s complete commit file list instead of falling back to only the latest commit.
- Pull request events diff the PR base SHA to the PR head SHA.
- If the resolver cannot prove the full range, it leaves changed-file state unavailable so Vercel gating defaults open.
apps/<app>/**runs that app’s preview or production Vercel workflow.packages/<package>/**runs every Vercel app whose transitiveworkspace:*dependency closure includes that package.apps/*/package.jsonandpackages/*/package.jsonare dependency changes for their owning workspaces.bun.lock, rootpackage.json,turbo.json,tuturuuu.ts, and.github/workflows/ci-check.ymlrun every Vercel app workflow.- A Vercel workflow file change, such as
.github/workflows/vercel-preview-calendar.yaml, runs that specific workflow. - If changed files cannot be computed, the Vercel gate defaults open.
bun.lock-only changes intentionally run all Vercel app deploys because ownership
is ambiguous without a manifest or source path.
Main Workflow Groups
Hosted web deployments
vercel-preview-platform.yamlvercel-preview-apps.yamlvercel-preview-calendar.yamlvercel-preview-cms.yamlvercel-preview-finance.yamlvercel-preview-inventory.yamlvercel-preview-mail.yamlvercel-preview-meet.yamlvercel-preview-nova.yamlvercel-preview-qr.yamlvercel-preview-rewise.yamlvercel-preview-shortener.yamlvercel-preview-tasks.yamlvercel-preview-track.yamlvercel-preview-learn.yamlvercel-preview-teach.yaml- Matching
vercel-production-*.yamlworkflows for production
- preview workflow:
vercel-preview-cms.yaml - production workflow:
vercel-production-cms.yaml - project secret:
VERCEL_CMS_PROJECT_ID - environments:
vercel-preview-cmsandvercel-production-cms
- preview workflow:
vercel-preview-apps.yaml - production workflow:
vercel-production-apps.yaml - project secret:
VERCEL_APPS_PROJECT_ID - environments:
vercel-preview-appsandvercel-production-apps
- preview workflow:
vercel-preview-qr.yaml - production workflow:
vercel-production-qr.yaml - project secret:
VERCEL_QR_PROJECT_ID - environments:
vercel-preview-qrandvercel-production-qr
- preview workflow:
vercel-preview-mail.yaml - production workflow:
vercel-production-mail.yaml - project secret:
VERCEL_MAIL_PROJECT_ID - environments:
vercel-preview-mailandvercel-production-mail
- run with default
contents: readpermissions - bind deploy jobs to
vercel-preview-<app>orvercel-production-<app>GitHub Environments - run preview deployments only through manual dispatch from
main, with a requiredpreview_refinput and an actor present in theTRUSTED_PREVIEW_DEPLOY_ACTORSrepository variable - reject production manual dispatches from non-production branches before install/build/deploy work starts
- install Bun and Node 24
- install dependencies
- build selected shared workspace dependencies before Vercel resolves package exports:
@tuturuuu/types,@tuturuuu/supabase, and@tuturuuu/internal-api - run
vercel pull - run
vercel build - deploy prebuilt artifacts
- skip production push work when a newer commit already exists on the target branch
- record a non-blocking GitHub Deployment marker after a successful Vercel build/deploy so the next production push can evaluate every change since the last successful run
Database automation
supabase-staging.yamlsupabase-production.yamlsupabase-types.yaml
Docker automation
docker-setup-check.yamlgo-backend.yml
docker-setup-check.yaml is the workflow to watch whenever Docker files,
compose files, or Docker helper scripts change. go-backend.yml owns the
apps/backend Go service checks: formatting, module download, go vet, tests,
binary build, and Docker image build.
Quality and security
type-check.yamlturbo-unit-tests.yamlbiome-check.yamlcodeql.ymlcodecov.yamli18n-check.yamlcheck-migrations.ymlcheck-migration-timestamps.ymlbranch-name-check.yaml
turbo-unit-tests.yaml and codecov.yaml) run bun setup
before executing tests so dependency installation and workspace package builds
match the local setup path. Vercel workflows should invoke Turborepo through
bun turbo:local ... after bun install so CI uses the pinned repo dependency
instead of resolving a global or downloaded Turbo binary.
Vercel deploy credentials must stay environment-scoped. Do not put
${{ secrets.* }} values in a Vercel workflow-level env: block, and do not
export production Supabase, encryption, provider, or Turborepo remote-cache
secrets from GitHub Actions. Store app runtime and build-time configuration in
the Vercel project environment. The regression test
bun test scripts/ci/release-workflows.test.js enforces this for every
vercel-preview-*.yaml and vercel-production-*.yaml workflow.
Preview deploy credentials must not be exposed to arbitrary branch push code.
Preview Vercel workflows are manual-only: run the workflow from main, provide
the branch, tag, or SHA in preview_ref, and keep TRUSTED_PREVIEW_DEPLOY_ACTORS
limited to maintainers who can approve secret-backed preview builds. The workflow
still checks out and builds the requested preview_ref, so reviewers should
treat that ref as code that can execute during install/build.
Other delivery surfaces
discord-modal-deploy.ymlmobile-build-android.yamlmobile-build-ios.yamlmobile-build-macos.yamlmobile-build-windows.yamlrelease-*.yamlpackage publishing workflows
Operational Rules
Manual dispatch
Useworkflow_dispatch when:
- you need to rerun a deployment intentionally
- you need to promote a migration outside the normal trigger timing
- you need to recover from a failed but otherwise understood automation path
tuturuuu.ts. Disabled ci entries still skip, even for manual dispatch.
For preview Vercel deployments, dispatch the workflow from main, set
preview_ref to the branch, tag, or SHA to deploy, and confirm the actor is in
TRUSTED_PREVIEW_DEPLOY_ACTORS. Do not reintroduce preview push triggers for
secret-backed Vercel workflows.
Package release workflows that expose production secrets or trusted publishing
authority must add their own ref guard before dependency installation or publish
jobs. Release Please is the only workflow that generates monorepo version and
changelog PRs. It runs from production, uses
secrets.RELEASE_PLEASE_TOKEN so generated PRs and releases can trigger
downstream workflows, and falls back to github.token only to keep the job from
failing when the bot token is not provisioned. The github.token fallback does
not trigger downstream workflow runs from generated release PRs. Release Please
rejects non-production manual dispatches before the write-capable release job.
Package publish workflows consume release-please version bumps on production;
they must not recreate checksum or PR-title version bump automation. Package
release workflows use npm trusted publishing: build and artifact-pack work runs
before any OIDC permission is granted, then the publish-npm job downloads one
tarball, verifies its package name and version, and runs npm publish without
NPM_TOKEN. Each publish job is bound to its package release environment, and
the matching npm trusted publisher must use this repository, the workflow
filename, and that environment. Manual dispatch is only valid with the branch
selector set to production; non-production refs are rejected before the package
or publish jobs can start. Every workflow-published package manifest must also
declare repository.type: "git",
repository.url: "https://github.com/tutur3u/platform", and
repository.directory matching the package path. npm validates those fields
against GitHub Actions provenance and rejects publishes with E422 when the
packed manifest has an empty or mismatched repository URL.
Keep internal Tuturuuu dependencies as workspace:* in source package
manifests so local builds always use the checked-out workspace. Package release
workflows must first run
node scripts/ci/package-release-readiness.js wait-workspace-dependencies packages/<name>
so publishable Tuturuuu dependencies are visible on npm before the dependent
tarball is packed. That wait also inspects the dependency package workflow run
for the same production SHA and fails immediately when that related workflow has
already failed instead of burning the full npm polling timeout. It must then
rewrite the checked-out manifest immediately
before npm pack with
node scripts/ci/prepare-npm-package-manifest.js packages/<name>. That
temporary rewrite replaces workspace: protocol ranges with the current
workspace package versions so npm consumers can install the tarball. After
npm publish, the publish job polls npm view for the exact published version
before it reports success. If npm returns first-publish or permission errors,
fix the npm package access and trusted publisher setup instead of skipping the
package. If a published package depends on another release-please-managed
Tuturuuu package, that dependency also needs its own
release-*-package.yaml workflow and matching tuturuuu.ts entry.
The platform production Vercel workflow also runs
node scripts/ci/package-release-readiness.js wait-changed-package-versions
before installing dependencies. Release-please package bumps therefore publish
and become visible on npm before the normal production platform deployment flow
continues. When the push payload omits changed package files, the helper fetches
the missing base SHA before falling back to git diff, so shallow checkout
depth does not break the release gate.
Newer-commit guards
Production Vercel push workflows intentionally skip if the branch already has a newer commit than the current run. A skipped deployment may be correct rather than broken. The deployment marker closes the gap created by these stale-run skips. When a later push reaches the latest commit, affected-app gating compares against the last successful marker rather than only the newest push payload, so app changes from skipped intermediate runs still queue the correct Vercel workflow.Prerequisite guards
supabase-staging.yamlrequires a successfulmainpreview trigger unless manually dispatched.- Its deploy step links the staging project and runs
supabase db push --include-all. supabase-production.yamlruns after production deployment and also re-evaluates after a matchingmainstaging migration succeeds. It still checks both the latest production Vercel result and a completed successful staging migration for the same commit before runningsupabase db push.
Mobile iOS native assets
mobile-build-ios.yaml caches CocoaPods and the CocoaPods trunk cache only. Do
not cache apps/mobile/.dart_tool in this workflow: Flutter native asset hook
outputs can become stale across simulator/device builds and SDK updates. A stale
.dart_tool cache can leave NativeAssetsManifest.json referencing
objective_c while build/native_assets/ios/ is missing the generated
framework, which fails the simulator build during Xcode’s embed phase.
The workflow explicitly runs flutter config --no-enable-swift-package-manager
after Flutter setup. Keep the iOS CI path on CocoaPods while image_cropper and
dkimagepickercontroller resolve incompatible TOCropViewController Swift
package ranges; otherwise Flutter 3.44+ can fail before the simulator build
with an Xcode package dependency resolution error.
Fast Triage Checklist
- Check whether
ci-check.ymldisabled the workflow throughtuturuuu.ts. - For Vercel workflows, inspect the
ci-check.ymldecision reason and matched paths. - Inspect the changed-file source, base SHA, head SHA, and path count emitted by
resolve-changed-files.ts. - Check whether the workflow was skipped because a newer commit exists.
- Check whether the prior successful GitHub Deployment marker exists for that Vercel workflow and branch.
- Check path filters to confirm GitHub should have started the lightweight workflow.
- For database workflows, inspect the prerequisite evaluation job before the deploy job.
- For Docker changes, verify
docker-setup-check.yamlspecifically.
When You Add New Automation
- Add the workflow file under
.github/workflows/. - Add its key to
tuturuuu.tsunless you intentionally want it always on by default. - Document the workflow in
apps/docs. - If it changes a docs-visible page, add that page to
apps/docs/docs.json.