Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions .github/workflows/pages-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 11 additions & 7 deletions docs/gtfs-timetable-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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/<archive-sha256>.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 |

Expand Down
Loading