name: Publish Pages on: push: branches: [main] workflow_dispatch: jobs: publish: runs-on: ubuntu-latest container: image: node:22-bookworm env: R2_ENDPOINT: https://${{ secrets.F40_PAGES_R2_ACCOUNT_ID }}.r2.cloudflarestorage.com R2_ACCOUNT_ID: ${{ secrets.F40_PAGES_R2_ACCOUNT_ID }} R2_BUCKET: ${{ secrets.F40_PAGES_R2_BUCKET }} SITE_NAME_OVERRIDE: ${{ vars.F40_PAGES_SITE_NAME }} BUILD_COMMAND_OVERRIDE: ${{ vars.F40_PAGES_BUILD_COMMAND }} OUTPUT_DIR_OVERRIDE: ${{ vars.F40_PAGES_OUTPUT_DIR }} DEFAULT_BUILD_COMMAND: ${{ vars.F40_PAGES_DEFAULT_BUILD_COMMAND }} DEFAULT_OUTPUT_DIR: ${{ vars.F40_PAGES_DEFAULT_OUTPUT_DIR }} steps: - uses: actions/checkout@v4 - name: Resolve settings run: | SITE_NAME="${SITE_NAME_OVERRIDE:-${GITHUB_REPOSITORY##*/}}" BUILD_COMMAND="${BUILD_COMMAND_OVERRIDE:-${DEFAULT_BUILD_COMMAND:-npm ci && npm run build:test-app}}" OUTPUT_DIR="${OUTPUT_DIR_OVERRIDE:-${DEFAULT_OUTPUT_DIR:-dist}}" echo "SITE_NAME=$SITE_NAME" >> "$GITHUB_ENV" echo "BUILD_COMMAND=$BUILD_COMMAND" >> "$GITHUB_ENV" echo "OUTPUT_DIR=$OUTPUT_DIR" >> "$GITHUB_ENV" - name: Validate publish settings env: AWS_ACCESS_KEY_ID: ${{ secrets.F40_PAGES_R2_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.F40_PAGES_R2_SECRET_ACCESS_KEY }} run: | missing=0 for name in R2_ACCOUNT_ID R2_BUCKET AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY; do value="$(eval "printf '%s' \"\${$name:-}\"")" if [ -z "$value" ]; then echo "::error::$name is required" missing=1 fi done if [ "$missing" -ne 0 ]; then exit 1 fi case "$SITE_NAME" in ""|*[!A-Za-z0-9._-]*) echo "::error::SITE_NAME must contain only letters, numbers, '.', '_', and '-'" exit 1 ;; esac - name: Install AWS CLI run: | if ! command -v aws >/dev/null 2>&1; then apt-get update apt-get install -y --no-install-recommends awscli rm -rf /var/lib/apt/lists/* fi - name: Build static site run: sh -c "$BUILD_COMMAND" - name: Validate build output run: | if [ ! -d "$OUTPUT_DIR" ]; then echo "::error::Build output directory '$OUTPUT_DIR' does not exist" exit 1 fi if [ ! -f "$OUTPUT_DIR/index.html" ]; then echo "::warning::'$OUTPUT_DIR/index.html' does not exist; /$SITE_NAME/ will return 404" fi - name: Publish to R2 env: AWS_ACCESS_KEY_ID: ${{ secrets.F40_PAGES_R2_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.F40_PAGES_R2_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: auto run: | RUN_ATTEMPT="${GITHUB_RUN_ATTEMPT:-1}" RELEASE="${GITHUB_SHA}-${RUN_ATTEMPT}" PREFIX="sites/${SITE_NAME}/releases/${RELEASE}" PUBLISHED_AT="$(date -u +%Y-%m-%dT%H:%M:%SZ)" aws s3 sync "$OUTPUT_DIR/" "s3://${R2_BUCKET}/${PREFIX}/" \ --endpoint-url "$R2_ENDPOINT" \ --delete \ --cache-control "public,max-age=31536000,immutable" printf '{"site":"%s","release":"%s","sha":"%s","publishedAt":"%s"}\n' \ "$SITE_NAME" "$RELEASE" "$GITHUB_SHA" "$PUBLISHED_AT" > current.json aws s3 cp current.json "s3://${R2_BUCKET}/sites/${SITE_NAME}/current.json" \ --endpoint-url "$R2_ENDPOINT" \ --content-type application/json \ --cache-control no-store