A web-based system to anonymously select developers for JumboCode teams.
Restore db_cluster-18-10-2024@11-18-20.backup when starting from the 2024
database, then apply the migrations in supabase/migrations in filename order.
The normalized-selection migration:
- backfills the comma-separated
dev_selectionsvalues into onedeveloper_selectionsrow per developer and team; - creates locked database functions for selection, removal, submission, and Board approval;
- enables RLS and removes direct write grants;
- seeds every existing Board user with every existing team in
board_selection_scopes; and - adds the normalized table to the Supabase Realtime publication.
The legacy dev_selections table is intentionally retained for rollout
verification, but the application no longer reads or writes it. Remove it in a
later migration only after comparing the backfilled rows in production.
Board access is explicit. Add or remove rows in board_selection_scopes with a
trusted administrator/service-role connection when a Board member's scope
changes.
All selection writes go through set_developer_selection and
remove_developer_selection. These functions lock the applicable
team_status row. submit_team_selections takes the same lock, verifies exactly
10 selected developers and 1–3 waitlisted developers, and atomically changes
the status to Under Review. Team users cannot edit after submission; scoped
Board users can edit during review and can finalize it with
approve_team_selections.
The Astro server creates a new Supabase client for every request. Browser code receives only the access token needed for Realtime and sends mutations to the same-origin API; refresh tokens remain in HTTP-only cookies.
- Clone the repository
- Create a
.envfile in the root directory with the following entries:
- SUPABASE_DB_URI (uri to directly access the supabase DB)
- Apply the migrations (
npx supabase db push).202609240001_setup_2026_27_cycle.sqlswaps in the 2026–27 ranking/question columns and resetsteam_statusto the eight 2026–27 teams. Team slugs (e.g.damiens_place) are theteam_status.team_name, the/dev-selection/<team>URL, and therank_<team>column suffix, so the script'sshort_column_namesand the migration must agree. Then add each team lead touser_roles(email,role,team_name= slug,first_name) and give them a Supabase Auth login. Board members added after the migration also need rows inboard_selection_scopes. - In the root directory run
./scripts/run_scripts.ps1(if on Windows; pass-ApplicationsCsv <path>to use a different export) orpython ./scripts/parse_application_data.py <applications.csv> ./data/lotr_names.csv. The script checks the CSV header againstfull_column_namesand stops before touching the database if a new form's questions don't match. To dump script outputs in a directory other than the root, specify an absolute path using the-oflag. For help on how to run the Python script, runpython ./scripts/parse_application_data.py -h.
Importing applications starts a new selection cycle: it clears both normalized and legacy selection rows before replacing application rows. Existing table schemas, foreign keys, and RLS policies are preserved.
Run the compiler and production build:
ASTRO_TELEMETRY_DISABLED=1 npm run buildThe concurrency suite uses separate authenticated Supabase clients and checks
cross-team writes, duplicate clicks, permissions, direct-write denial, and the
selection-versus-submission race. It is destructive by design and must only run
against a dedicated test project. Copy .env.test.example, provide disposable
users and fake names, load those variables, then run:
npm run test:concurrencyThe app uses Astro 5 and the Vercel 8 adapter. Use Node.js 22.12 or newer within
the Node 22 release line, and configure the Vercel project to use Node.js 22.x.
The adapter derives the function runtime from the Node version running the build.
npm ci
ASTRO_TELEMETRY_DISABLED=1 npm run buildBefore deploying, verify that .vercel/output/functions/_render.func/.vc-config.json
contains "runtime": "nodejs22.x". A successful build alone does not guarantee
that the emitted runtime is supported by Vercel.
-
Create or select a non-production Supabase project.
-
Configure a Vercel Preview environment with the staging project's
SUPABASE_URLandSUPABASE_ANON_KEY. -
Do not put
SUPABASE_SERVICE_ROLE_KEYorSUPABASE_DB_URIin Vercel. -
Apply the migration to staging from the repository root:
npx supabase login npx supabase link --project-ref YOUR_STAGING_PROJECT_REF npx supabase migration list npx supabase db push --dry-run npx supabase db push
-
Run the concurrency suite against staging using
.env.test.example. -
Deploy the feature branch as a Vercel Preview and verify:
- simultaneous selections by multiple teams are all retained;
- selected/waitlisted changes update in both browsers through Realtime;
- a team cannot change another team's selections;
- invalid counts cannot be submitted;
- valid submission blocks further team changes; and
- scoped Board users can review and approve the team.
Perform the cutover while selection activity is paused. The database migration must be applied before the new application, but it also revokes the old application's write access, so keep the interval between these steps short.
-
Pause selection activity and confirm a current Supabase backup under Database > Backups.
-
Link the Supabase CLI to the production project:
npx supabase link --project-ref YOUR_PRODUCTION_PROJECT_REF npx supabase migration list npx supabase db push --dry-run
-
Confirm that the dry run lists only the expected normalized-selection migration, then apply it:
npx supabase db push
-
Confirm
developer_selectionswas backfilled and review the generatedboard_selection_scopesrows. -
Merge the tested feature branch into the Vercel production branch, normally
main, or explicitly promote the tested deployment. -
Smoke-test team login, selection, Realtime, submission, Board approval, and sign-out before resuming selection activity.
-
Monitor Vercel function logs and Supabase API/database logs during the first live selection period.
Do not roll back only the Vercel application after the migration: the old application writes the deprecated table. Prefer a fix-forward. A full rollback requires restoring the pre-cutover database backup and the prior Vercel deployment, which can discard selections made after the backup.