From d735431ad458fafdf7354c0980d4f6c7062d4374 Mon Sep 17 00:00:00 2001 From: Duncan Leo Date: Sun, 15 Nov 2026 13:39:39 -0800 Subject: [PATCH] fix: fetch Pages timetable inputs from Tigris Co-Authored-By: Codex --- .github/workflows/pages-deploy.yml | 15 +++++++++------ docs/gtfs-timetable-release.md | 18 +++++++++++------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/.github/workflows/pages-deploy.yml b/.github/workflows/pages-deploy.yml index 5b79ff99..49dd7af0 100644 --- a/.github/workflows/pages-deploy.yml +++ b/.github/workflows/pages-deploy.yml @@ -64,22 +64,25 @@ jobs: - name: Acquire approved combined timetable inputs if: env.COMBINED_TIMETABLE_ENABLED == 'true' env: - RELEASE_URL: ${{ secrets.MRTDOWN_COMBINED_TIMETABLE_INPUT_URL }} - RELEASE_TOKEN: ${{ secrets.MRTDOWN_COMBINED_TIMETABLE_INPUT_TOKEN }} + RELEASE_BUCKET: ${{ vars.MRTDOWN_COMBINED_TIMETABLE_INPUT_BUCKET }} RELEASE_SHA256: ${{ vars.MRTDOWN_COMBINED_TIMETABLE_INPUT_SHA256 }} + RELEASE_ACCESS_KEY_ID: ${{ secrets.MRTDOWN_COMBINED_TIMETABLE_INPUT_ACCESS_KEY_ID }} + RELEASE_SECRET_ACCESS_KEY: ${{ secrets.MRTDOWN_COMBINED_TIMETABLE_INPUT_SECRET_ACCESS_KEY }} run: | umask 077 - if [[ "$RELEASE_URL" != https://* || -z "$RELEASE_TOKEN" || ! "$RELEASE_SHA256" =~ ^[a-f0-9]{64}$ ]]; then - echo "::error::A private HTTPS release URL, bearer token and pinned archive SHA-256 are required" + if [[ ! "$RELEASE_BUCKET" =~ ^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$ || ! "$RELEASE_SHA256" =~ ^[a-f0-9]{64}$ || -z "$RELEASE_ACCESS_KEY_ID" || -z "$RELEASE_SECRET_ACCESS_KEY" ]]; then + echo "::error::A private Tigris bucket, S3 read credentials and pinned archive SHA-256 are required" exit 1 fi input_dir="$RUNNER_TEMP/combined-release" archive="$RUNNER_TEMP/combined-release-inputs.tar.gz" + release_url="https://t3.storage.dev/$RELEASE_BUCKET/pages-release-inputs/$RELEASE_SHA256.tar.gz" mkdir "$input_dir" status=$(curl --fail --show-error --silent --proto '=https' \ --max-time 120 --max-filesize 67108864 \ - --header "Authorization: Bearer ${RELEASE_TOKEN}" \ - --output "$archive" --write-out '%{http_code}' "$RELEASE_URL") + --aws-sigv4 'aws:amz:auto:s3' \ + --user "$RELEASE_ACCESS_KEY_ID:$RELEASE_SECRET_ACCESS_KEY" \ + --output "$archive" --write-out '%{http_code}' "$release_url") if [[ "$status" != 200 ]]; then echo "::error::Private release download must return HTTP 200 directly" exit 1 diff --git a/docs/gtfs-timetable-release.md b/docs/gtfs-timetable-release.md index bed45062..76c1b71a 100644 --- a/docs/gtfs-timetable-release.md +++ b/docs/gtfs-timetable-release.md @@ -278,7 +278,7 @@ and the fixture export omit combined timetable output. ### Deploying the combined release through GitHub Actions -The main-branch Pages workflow uses the repository variable +The main-branch Pages workflow uses the `github-pages` environment variable `MRTDOWN_COMBINED_TIMETABLE_ENABLED`. Leave it unset or set to `false` until publication and production import are authorized. When set to `true`, every routine deployment rebuilds the pinned release against the canonical data it @@ -304,18 +304,22 @@ Pages tree. Include `schedule.zip`, the licence-reviewed `capture.json`, The builder checks fresh terms and release eligibility, then verifies and preserves the original evidence bytes. This keeps both index digests stable -across deployments of the same release. Use an immutable private HTTPS object -that serves the archive directly with bearer authentication. Keep the raw -archive, review inputs and source review in private storage. PR checks use -synthetic timetables and Pages previews use the default build. +across deployments of the same release. In the private Tigris bucket, store the +archive at `pages-release-inputs/.tar.gz`. The workflow signs an +S3 GET request to Tigris and checks the downloaded archive against the pinned +digest. Give the workflow its own credentials scoped to `s3:GetObject` under +`pages-release-inputs/`. Keep the raw archive, review inputs and source review in +private storage. PR checks use synthetic timetables and Pages previews use the +default build. Restrict the `github-pages` environment to `main` before storing the release credentials. Configure the following on that environment while the gate is off. | Setting | Value | | --- | --- | -| Secret `MRTDOWN_COMBINED_TIMETABLE_INPUT_URL` | Private archive URL | -| Secret `MRTDOWN_COMBINED_TIMETABLE_INPUT_TOKEN` | Read-only bearer token for that archive | +| Variable `MRTDOWN_COMBINED_TIMETABLE_INPUT_BUCKET` | Private Tigris bucket name | +| Secret `MRTDOWN_COMBINED_TIMETABLE_INPUT_ACCESS_KEY_ID` | Scoped Tigris S3 access key ID | +| Secret `MRTDOWN_COMBINED_TIMETABLE_INPUT_SECRET_ACCESS_KEY` | Scoped Tigris S3 secret access key | | Variable `MRTDOWN_COMBINED_TIMETABLE_INPUT_SHA256` | SHA-256 of the exact compressed archive | | Secret `MRTDOWN_COMBINED_TIMETABLE_SOURCE_REVIEW` | Production-approved `scheduled-timetable-source-review` JSON |