Skip to content

docs(compose): rebuild design, analysis & adversarial review notes #14

docs(compose): rebuild design, analysis & adversarial review notes

docs(compose): rebuild design, analysis & adversarial review notes #14

Workflow file for this run

name: Publish @my-own-web-services/react-components docs
# Deploys to https://my-own-web-services.github.io/mows-react-components/
#
# Publishing model: this workflow builds the docs SPA, then pushes it into
# the org Pages repo `my-own-web-services/my-own-web-services.github.io`
# under the `mows-react-components/` subdirectory. That repo hosts every
# project's docs as siblings (mows-react-components/, mows-vm-supervisor/,
# …) so each docs workflow only owns its own subdir and never touches the
# others.
#
# Prerequisites (one-time, done out-of-band):
# 1. Org Pages repo `my-own-web-services/my-own-web-services.github.io`
# exists, public, Pages enabled with Source = "Deploy from a branch"
# (main, /).
# 2. An SSH deploy key has been generated. The PUBLIC half is added to
# the org Pages repo as a deploy key with write access. The PRIVATE
# half is stored on THIS repo as the `DOCS_DEPLOY_KEY` secret.
on:
push:
branches:
- main
paths:
- 'components/react/**'
- '.github/workflows/publish-docs.yml'
pull_request:
paths:
- 'components/react/**'
- '.github/workflows/publish-docs.yml'
workflow_dispatch:
inputs:
site_base:
description: 'Public base path the site is served from (must start AND end with "/"). Default "/mows-react-components/" matches the org Pages layout.'
required: false
default: '/mows-react-components/'
type: string
# Serialise pushes to the org Pages repo so a newer commit on main always
# wins. PRs run the build alone (no deploy) so they cancel freely.
concurrency:
group: publish-docs-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
permissions:
contents: read
env:
# Slug used both as the URL path prefix and the subdirectory inside the
# org Pages repo. Changing this in one place keeps the build and the
# deploy in sync.
DOCS_SLUG: mows-react-components
PAGES_REPO: my-own-web-services/my-own-web-services.github.io
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4
- name: Set up Node.js
uses: actions/setup-node@26961cf329f22f6837d5f54c3efd76b480300ace # v4
with:
node-version: '22'
- name: Set up pnpm
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4
with:
version: 9.15.9
run_install: false
- name: Get pnpm store path
id: pnpm-store
run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
- name: Cache pnpm store
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v4
with:
path: ${{ steps.pnpm-store.outputs.path }}
key: ${{ runner.os }}-pnpm-${{ hashFiles('components/react/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-
- name: Build docs site
env:
SITE_BASE: ${{ github.event.inputs.site_base || format('/{0}/', env.DOCS_SLUG) }}
run: |
cd components/react
bash scripts/build-docs.sh
# Hand the built `dist-site/` to the deploy job via the standard
# artifact channel. Plain workflow artifact — NOT a Pages artifact —
# since we publish to a different repo, not this repo's Pages.
- name: Upload built site
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: docs-site
path: components/react/dist-site
retention-days: 7
if-no-files-found: error
deploy:
needs: build
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment:
name: docs-publish
url: https://my-own-web-services.github.io/${{ env.DOCS_SLUG }}/
steps:
- name: Download built site
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
with:
name: docs-site
path: dist-site
- name: Configure SSH for org Pages repo
env:
DEPLOY_KEY: ${{ secrets.DOCS_DEPLOY_KEY }}
run: |
if [ -z "${DEPLOY_KEY}" ]; then
echo "::error::DOCS_DEPLOY_KEY secret is not configured on this repo."
echo "Generate an ed25519 keypair, add the public half as a deploy key"
echo "(with write access) on ${PAGES_REPO}, and add the private half as"
echo "the DOCS_DEPLOY_KEY secret on this repo."
exit 1
fi
mkdir -p ~/.ssh
chmod 700 ~/.ssh
printf '%s\n' "${DEPLOY_KEY}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
ssh-keyscan -t ed25519,rsa github.com >> ~/.ssh/known_hosts 2>/dev/null
- name: Publish to org Pages repo
env:
SOURCE_SHA: ${{ github.sha }}
run: |
set -euo pipefail
# Shallow clone to keep the deploy fast; we only need HEAD to make
# one new commit on top of it.
git clone --depth 1 "git@github.com:${PAGES_REPO}.git" pages-repo
cd pages-repo
# Replace only OUR subdir; siblings (other docs projects) stay
# untouched. rsync --delete prunes files that disappeared
# between builds, but the --include patterns confine all
# deletes to ${DOCS_SLUG}/.
rm -rf "${DOCS_SLUG}"
mkdir "${DOCS_SLUG}"
cp -a ../dist-site/. "${DOCS_SLUG}/"
git config user.name "mows-docs-bot"
git config user.email "mows-docs-bot@users.noreply.github.com"
git add "${DOCS_SLUG}"
if git diff --staged --quiet; then
echo "No changes to publish (build is byte-identical to the live site)."
exit 0
fi
SHORT_SHA="${SOURCE_SHA:0:7}"
git commit -m "docs(${DOCS_SLUG}): publish ${SHORT_SHA}"
# Retry on push rejection — another docs workflow (e.g. a sibling
# project) may have pushed concurrently. We only touch our own
# subdir, so a rebase is always trivial; bail after a few tries
# to avoid burning runner time on a genuinely broken state.
for attempt in 1 2 3 4 5; do
if git push origin HEAD:main; then
echo "Published ${DOCS_SLUG}@${SHORT_SHA} -> ${PAGES_REPO}"
exit 0
fi
echo "Push attempt ${attempt} rejected; rebasing on latest main…"
git fetch --depth 1 origin main
git rebase origin/main
done
echo "::error::Failed to push after 5 attempts."
exit 1