Skip to content

Deploy project site v0.1.22 7520b1ee-8304-4d58-aac6-301c161e4911 #48

Deploy project site v0.1.22 7520b1ee-8304-4d58-aac6-301c161e4911

Deploy project site v0.1.22 7520b1ee-8304-4d58-aac6-301c161e4911 #48

Workflow file for this run

name: Deploy project site
run-name: Deploy project site ${{ inputs.release_tag || github.ref_name }} ${{ inputs.dispatch_nonce || github.sha }}
on:
push:
branches: [main, master]
paths:
- "apps/site/**"
- "scripts/check-release-publication.mjs"
- "scripts/deploy-site.mjs"
- "scripts/dispatch-site-deployment.mjs"
- "scripts/generate-release-manifest.mjs"
- "scripts/inspect-linux-update.mjs"
- "scripts/read-bounded-response.mjs"
- "scripts/reconcile-release-assets.mjs"
- "scripts/wait-for-release-assets.mjs"
- "package.json"
- "pnpm-lock.yaml"
- ".github/workflows/deploy-site.yml"
workflow_dispatch:
inputs:
release_tag:
description: Published release tag whose immutable source must be deployed.
required: true
type: string
dispatch_nonce:
description: Unique release-workflow dispatch identity.
required: true
type: string
permissions:
contents: read
id-token: write
concurrency:
group: t4code-net-production
cancel-in-progress: false
jobs:
deploy:
if: ${{ github.event_name != 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/') }}
runs-on: ubuntu-24.04
timeout-minutes: 50
environment:
name: production
url: https://t4code.net
steps:
- name: Check out trusted workflow source
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
ref: ${{ github.sha }}
fetch-depth: 0
persist-credentials: false
- name: Read trusted workflow source version
id: source
shell: bash
env:
TRUSTED_SHA: ${{ github.sha }}
run: |
set -euo pipefail
version=$(node -p "require('./package.json').version")
printf 'version=%s\ntrusted_sha=%s\n' "$version" "$TRUSTED_SHA" >> "$GITHUB_OUTPUT"
- name: Install pnpm
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
with:
version: 11.10.0
- name: Install Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 24.13.1
- name: Confirm the published release from the release workflow
id: published_release
if: ${{ github.event_name == 'workflow_dispatch' }}
env:
RELEASE_VERSION: ${{ steps.source.outputs.version }}
run: node scripts/wait-for-release-assets.mjs --version "$RELEASE_VERSION" --timeout-ms 2400000 --interval-ms 15000
- name: Classify the stable release referenced by an ordinary main push
id: release_state
if: ${{ github.event_name == 'push' }}
env:
GH_TOKEN: ${{ github.token }}
RELEASE_VERSION: ${{ steps.source.outputs.version }}
run: node scripts/check-release-publication.mjs --version "$RELEASE_VERSION" --github-output "$GITHUB_OUTPUT"
- name: Confirm assets for an existing stable release
id: existing_release
if: ${{ github.event_name == 'push' && steps.release_state.outputs.state == 'published' }}
env:
RELEASE_VERSION: ${{ steps.source.outputs.version }}
run: node scripts/wait-for-release-assets.mjs --version "$RELEASE_VERSION" --timeout-ms 15000 --interval-ms 3000
- name: Defer a release-version site update until publication
if: ${{ github.event_name == 'push' && steps.release_state.outputs.state == 'not-published' }}
run: echo "The referenced release is not public yet; the release workflow will deploy this site after publication."
- name: Resolve immutable deployment source
id: immutable_source
if: ${{ steps.published_release.outcome == 'success' || steps.existing_release.outcome == 'success' }}
shell: bash
env:
EVENT_NAME: ${{ github.event_name }}
GH_TOKEN: ${{ github.token }}
TRUSTED_SHA: ${{ steps.source.outputs.trusted_sha }}
REQUESTED_RELEASE_TAG: ${{ inputs.release_tag }}
TRUSTED_VERSION: ${{ steps.source.outputs.version }}
run: |
set -euo pipefail
expected_tag="v${TRUSTED_VERSION}"
release_tag="$expected_tag"
if [[ "$EVENT_NAME" == "workflow_dispatch" ]]; then
if [[ "$REQUESTED_RELEASE_TAG" != "$expected_tag" ]]; then
echo "release_tag must be the current release ${expected_tag}" >&2
exit 1
fi
if [[ "$GITHUB_REF" != "refs/tags/${expected_tag}" ]]; then
echo "workflow_dispatch must run from the immutable release tag ${expected_tag}" >&2
exit 1
fi
release_tag="$REQUESTED_RELEASE_TAG"
fi
release_flags=$(gh api "repos/${GITHUB_REPOSITORY}/releases/tags/${release_tag}" --jq '[.draft, .prerelease] | @tsv')
if [[ "$release_flags" != $'false\tfalse' ]]; then
echo "release_tag must name a published, non-prerelease GitHub release" >&2
exit 1
fi
git fetch --force origin "refs/tags/${release_tag}:refs/tags/${release_tag}"
source_sha=$(git rev-parse "${release_tag}^{commit}")
tag_version=$(git show "${source_sha}:package.json" | jq -er '.version')
if [[ "$tag_version" != "$TRUSTED_VERSION" ]]; then
echo "release tag package version ${tag_version} does not match trusted source ${TRUSTED_VERSION}" >&2
exit 1
fi
if [[ "$EVENT_NAME" == "workflow_dispatch" ]]; then
if [[ "$source_sha" != "$TRUSTED_SHA" ]]; then
echo "release tag moved after this immutable deployment was dispatched" >&2
exit 1
fi
elif ! git merge-base --is-ancestor "$source_sha" "$TRUSTED_SHA"; then
echo "release tag source is not reachable from the trusted workflow source" >&2
exit 1
fi
printf 'release_tag=%s\nsource_sha=%s\n' "$release_tag" "$source_sha" >> "$GITHUB_OUTPUT"
- name: Check out immutable deployment source
if: ${{ steps.published_release.outcome == 'success' || steps.existing_release.outcome == 'success' }}
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
ref: ${{ steps.immutable_source.outputs.source_sha }}
persist-credentials: false
- name: Install dependencies
if: ${{ steps.published_release.outcome == 'success' || steps.existing_release.outcome == 'success' }}
run: pnpm install --frozen-lockfile
- name: Authenticate to AWS with GitHub OIDC
if: ${{ steps.published_release.outcome == 'success' || steps.existing_release.outcome == 'success' }}
uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4
with:
role-to-assume: ${{ vars.AWS_ROLE_ARN }}
aws-region: us-east-1
- name: Build and deploy static site
if: ${{ steps.published_release.outcome == 'success' || steps.existing_release.outcome == 'success' }}
env:
GH_TOKEN: ${{ github.token }}
T4_SITE_BUCKET: ${{ vars.T4_SITE_BUCKET }}
T4_CLOUDFRONT_DISTRIBUTION_ID: ${{ vars.T4_CLOUDFRONT_DISTRIBUTION_ID }}
run: pnpm deploy:site