Scripts¶
Catalog of helper scripts that live outside task targets. Anything you'd run by hand to bootstrap, release, or troubleshoot.
Root scripts (scripts/)¶
| Script | What it does | When to use it |
|---|---|---|
pull-secrets.sh |
Pulls backend secrets from GCP Secret Manager and either exports them to the current shell, or execs the backend with them injected. No secrets are written to disk. |
Daily local dev once you're past first-time setup. |
release.sh |
Validates the current branch, computes the next semver tag, writes backend/VERSION and frontend/VERSION, pushes the tag, and creates a GitHub Release. The tag push is what triggers Cloud Build. |
Cutting a production release. |
run_e2e.sh |
Boots the full docker-compose stack, waits for backend (/health) and frontend to be reachable, runs Playwright tests in e2e/, and (optionally) tears the stack down. |
Running E2E suite against a clean local environment. |
setup-capture.sh |
One-shot, idempotent bring-up of the link-capture / enrichment pipeline: checks host prerequisites, installs Go deps, starts the local stack (Postgres, Redis, MinIO, Photon), starts the self-hosted LLM server (Ollama) and pulls the resolver model, and seeds the capture env keys into backend/.env.local. |
First time you want to capture a link locally and watch it resolve a place + discovered links. |
pull-secrets.sh¶
# Most common: export into current shell, then run task dev
eval $(./scripts/pull-secrets.sh)
task dev
# Or pull and run backend directly in one shot
./scripts/pull-secrets.sh --run
# Pull infra secrets (DB password, etc.) from GCP too — by default these
# use local docker-compose defaults
./scripts/pull-secrets.sh --run --full
Prerequisites: gcloud auth login + gcloud config set project development-485000.
task db:seed:catalog uses the same gcloud-login-gated pattern to pull the published location seed set from the GCS bucket and load it into local Postgres, skipping the 14 GB global Overture file (you still get countries, cities, admin areas, curated prestige lists, and Wikidata notable places, just not the bulk Overture POI dump). Override the published version with SEED_VERSION=<tag> (defaults to the latest) and the per-city promotion with CITY_HIGHLIGHTS=<n>. Prerequisite: local compose up (task dev).
release.sh¶
./scripts/release.sh
# Prompts for next version (suggests patch/minor/major bumps),
# pushes the tag, and creates the GitHub release.
Must be run on main with a clean working tree.
run_e2e.sh¶
./scripts/run_e2e.sh
# Builds and starts compose stack, waits for /health, runs Playwright,
# prompts at the end whether to tear down.
Works with both docker and podman (auto-detects). Report at e2e/playwright-report/index.html.
Backend scripts (backend/scripts/)¶
| Script | What it does | When to use it |
|---|---|---|
setup_stripe.sh |
Sources STRIPE_SECRET_KEY from env or a .env file, initialises a Go module locally, installs deps, and runs create_stripe_prices.go. |
One-time when bootstrapping a Stripe test account, or when product/price catalog changes. |
create_stripe_prices.go |
The actual Stripe SDK script — creates the Tomoda products and price IDs in the configured Stripe account. | Invoked via setup_stripe.sh; not run standalone. |
split_schema.py |
Splits a pg_dump -s dump (stdin) into the per-domain db/schema/*.sql snapshot sqlc generates against. Honors SCHEMA_OUT_DIR. |
Invoked by task db:schema (and the drift check); not run standalone. |
schema-drift-check.sh |
Applies db/migrations to a throwaway DB, dumps its schema, and diffs against db/schema/. Fails on drift; skips when Postgres is down (hard-fails under CI=true). |
Invoked by task db:schema:verify, CI, and the pre-commit hook. |
cd backend/scripts
./setup_stripe.sh
Outputs the new product / price IDs — paste them into backend/config.{env}.yaml under stripe.price_ids.
Frontend scripts (frontend/scripts/)¶
| Script | What it does | When to use it |
|---|---|---|
compare_i18n.js |
Walks frontend/i18n/locales/en-US.json and compares its key set against zh-TW.json, ja-JP.json, zh-CN.json. Reports keys missing from any target and keys present in a target but absent from English (orphans). |
Before every release, catches dropped translations. |
build-luts.js |
Converts every .cube color LUT in frontend/assets/luts/ to a 512x512 Hald PNG (trilinear-upsampling the 33-cube source to 64-cube), writing {name}.png next to each source. The PNGs feed the Skia LUT shader used by the camera/photo filters. |
After adding or editing a .cube filter. |
gen-share-locales.js |
Generates the OS share-card's localized strings for both platforms from one source (39-locale coverage), emitting the iOS extension's Localizable.strings and the Android target's strings.xml (keys share_saved_title, share_go_to_plan). |
After editing the share-card translations. |
bump-version.js |
Increments the iOS build number + Android versionCode in frontend/native-build.json (monotonic, required for every store upload), and for patch/minor/major also bumps the marketing version in package.json. Driven by task native:version:*. |
Before cutting a native binary. |
build-with-secrets.sh |
Pulls EXPO_PUBLIC_SENTRY_DSN and SENTRY_AUTH_TOKEN from GCP Secret Manager (no values written to disk), then runs the matching release-build command. ios/android exec expo run:* (Release build onto a device); ios-archive/android-bundle produce the signed store artifacts (.ipa / .aab); web runs expo export --platform web followed by sentry-cli sourcemaps upload. Default project development-485000 (override with GCP_PROJECT=…). |
Cutting a native release build, OR producing a web bundle with source maps uploaded to Sentry. Local dev (expo start) doesn't need it, since Sentry no-ops when DSN is empty. |
cd frontend
node scripts/compare_i18n.js
The script resolves localesDir relative to its own location via import.meta.url, so it works on any checkout.
build-with-secrets.sh¶
cd frontend
# iOS release build
./scripts/build-with-secrets.sh ios
# Android release build
./scripts/build-with-secrets.sh android
# Signed store artifacts (prebuild + archive/bundle)
./scripts/build-with-secrets.sh ios-archive # -> build/ios/ipa/*.ipa
./scripts/build-with-secrets.sh android-bundle # -> android/app/build/outputs/bundle/release/app-release.aab
# Regenerate native projects (ios/ and android/) before a release build if app.config.js changed
./scripts/build-with-secrets.sh prebuild
# Web export + Sentry source-map upload (release name: com.tomoda.app@<package.json version>)
./scripts/build-with-secrets.sh web
Prerequisites: gcloud CLI installed and authenticated (gcloud auth login), with secretAccessor permission on tomoda-sentry-dsn and tomoda-sentry-auth-token in project development-485000. The script aborts with a clear error if either gcloud isn't on PATH, gcloud isn't authenticated, or a secret can't be read.
Secret values are exported into the script process only — never written to disk — and inherited by the child expo / sentry-cli process via exec (native) or in the same shell (web). The shell history captures only the script invocation, not the secret values.
For web specifically: the wrapper runs expo export --platform web into dist/, then calls sentry-cli releases new/sourcemaps upload/releases finalize with --strip-prefix set to the frontend directory so the uploaded artifact paths match what's served from the CDN. The release name is com.tomoda.app@<version from package.json>, override with SENTRY_RELEASE=<custom> if you need a different identifier.
When to reach for the locale-reconcile skill instead¶
For more than a "what's missing?" check — automatic key extraction, hardcoded-string sweeps, orphan removal — see the locale-reconcile skill. It's the supported tool for substantive i18n maintenance; compare_i18n.js is just the diff reporter.