๐ŸŒ GitHub Pages Failover Runbook

March 12, 2026 ยท View on GitHub

Last updated: 2026-03-12 Owner: BCP Team Trigger: AWS S3 + CloudFront extended outage (>30 minutes)


๐Ÿ“‹ Prerequisites

  • Local clone of the repository
  • Node.js (current production version) installed
  • GitHub account with push access to the repository
  • Access to GitHub repository Settings โ†’ Pages

๐Ÿš€ Failover Procedure

Step 1: Build and Prepare Content

Run npm ci (preferred, when package-lock.json is present; otherwise run npm install) and npm run build locally to compile TypeScript into ./scripts. If news content or index/sitemap files need to be regenerated, also run npm run generate-news (and any other required content-generation commands) so that the repository root contains the up-to-date HTML entry points, news/ directory, and generated index/sitemap files.

# Prefer npm ci for reproducible builds (matches CI pipeline)
if [ -f package-lock.json ]; then
  npm ci
else
  npm install
fi
npm run build
npm run generate-news  # if content regeneration is needed

Step 2: Create Deployable Branch

Create or update a gh-pages branch that contains only the deployable static site artifacts: the root HTML files (index.html, index-*.html), the news/ directory, the scripts/ directory, and the generated sitemap (sitemap.xml). The procedure first saves the build artifacts from the current working tree into a temporary directory, then creates an orphan branch with a clean state, and copies the artifacts back in.

# Save the deployable artifacts from the current working tree into a temporary directory
TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT ERR
cp -p index.html "$TMP_DIR"/ 2>/dev/null || true
cp -p index-*.html "$TMP_DIR"/ 2>/dev/null || true
cp -pr news "$TMP_DIR"/ 2>/dev/null || true
cp -pr scripts "$TMP_DIR"/ 2>/dev/null || true
cp -p sitemap.xml "$TMP_DIR"/ 2>/dev/null || true

# If gh-pages branch already exists locally, delete it first
git branch -D gh-pages 2>/dev/null || true

# Create an orphan branch (no parent commits, clean working tree)
git checkout --orphan gh-pages

# Safety check: refuse to proceed if the working tree has uncommitted changes
# (artifacts were already saved to TMP_DIR above; this guards against accidental data loss)
if [ -n "$(git status --porcelain)" ]; then
  echo "WARNING: Working tree is not clean. Stash or discard local changes before proceeding."
  echo "Run: git stash  OR  git checkout -- ."
  exit 1
fi

# Remove all tracked files and clean untracked files from the working tree
git reset --hard
git clean -fdx

# Copy the deployable artifacts from the temporary directory into the repository root
cp -pr "$TMP_DIR"/. .

# Clean up the temporary directory
rm -rf "$TMP_DIR"

# Add and commit only the deployable artifacts
git add index.html ':(glob)index-*.html' news/ scripts/ sitemap.xml
git commit -m "Deploy static site to GitHub Pages (incident failover)"

Step 3: Deploy to GitHub Pages

Push the gh-pages branch to GitHub (force-push is expected since the orphan branch has no common history with any previous gh-pages contents):

git push --force origin gh-pages

Then configure GitHub Pages (under Settings โ†’ Pages) to serve from the gh-pages branch, root directory. Reference the configuration change (who/when/what) in the incident ticket so that it is auditable.

Step 4: Validate Availability

Wait for GitHub Pages to report as active, then validate availability using the GitHub Pages project page base URL for this repository:

  • Base URL: https://hack23.github.io/euparliamentmonitor

Validate that all 14 language variants are available at the following full URLs:

LanguageFull URL
Englishhttps://hack23.github.io/euparliamentmonitor/index.html
Swedishhttps://hack23.github.io/euparliamentmonitor/index-sv.html
Danishhttps://hack23.github.io/euparliamentmonitor/index-da.html
Norwegianhttps://hack23.github.io/euparliamentmonitor/index-no.html
Finnishhttps://hack23.github.io/euparliamentmonitor/index-fi.html
Germanhttps://hack23.github.io/euparliamentmonitor/index-de.html
Frenchhttps://hack23.github.io/euparliamentmonitor/index-fr.html
Spanishhttps://hack23.github.io/euparliamentmonitor/index-es.html
Dutchhttps://hack23.github.io/euparliamentmonitor/index-nl.html
Arabichttps://hack23.github.io/euparliamentmonitor/index-ar.html
Hebrewhttps://hack23.github.io/euparliamentmonitor/index-he.html
Japanesehttps://hack23.github.io/euparliamentmonitor/index-ja.html
Koreanhttps://hack23.github.io/euparliamentmonitor/index-ko.html
Chinesehttps://hack23.github.io/euparliamentmonitor/index-zh.html

Note: If this runbook is used from a fork, replace hack23 in the base URL with your GitHub username or organization.

Confirm that root HTML, news/, and the generated index and sitemap files load correctly.

Step 5: Record and Communicate

Record the fallback URL in the incident ticket and, if applicable, update status communications to direct users to the GitHub Pages fallback or alternative CDN endpoint.


๐Ÿ”„ Post-Incident Recovery

After the primary AWS S3 + CloudFront service is restored:

  1. Revert any manual GitHub Pages configuration changes
  2. Document the incident resolution in the incident ticket
  3. Validate the primary S3/CloudFront endpoint is fully operational
  4. If this fallback procedure is needed frequently, create a version-controlled workflow_dispatch workflow in .github/workflows/ to automate these steps

๐Ÿ“Ž References