Skip to content

docs-update

docs-update #179

name: Build and Deploy Docusaurus Documentation
on:
repository_dispatch:
types: [docs-update, docs-version-deploy]
workflow_dispatch:
inputs:
version:
description: 'Version to build (latest, v0.2.23, etc.)'
required: false
default: 'latest'
type: string
action:
description: 'Action to perform'
required: false
default: 'build-and-deploy'
type: choice
options:
- build-only
- deploy-only
- build-and-deploy
ogx_branch:
description: 'Branch of ogx to build from (default: main)'
required: false
default: 'main'
type: string
concurrency:
group: docs-build-deploy
cancel-in-progress: false
permissions:
contents: write
pages: write
id-token: write
jobs:
build:
if: ${{ github.event.inputs.action != 'deploy-only' }}
runs-on: ubuntu-latest
outputs:
building_latest: ${{ steps.set-version.outputs.building_latest }}
steps:
- name: Checkout this repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Clone ogx repository
id: set-version
run: |
echo "Cloning ogx repository..."
TEMP_DIR=$(mktemp -d)
echo "TEMP_DIR=$TEMP_DIR" >> $GITHUB_ENV
git clone https://github.com/${{ github.repository_owner }}/ogx.git "$TEMP_DIR/ogx"
cd "$TEMP_DIR/ogx"
git fetch --all --tags
# Determine version to checkout
VERSION="${{ github.event.client_payload.version || github.event.inputs.version || 'latest' }}"
if [ "$VERSION" = "latest" ] || [ -z "$VERSION" ]; then
LSBRANCH="${{ github.event.inputs.ogx_branch || 'main' }}"
LSBRANCH="${LSBRANCH:-main}"
git checkout "$LSBRANCH"
echo "Using branch: $LSBRANCH"
echo "BUILDING_LATEST=true" >> $GITHUB_ENV
echo "building_latest=true" >> $GITHUB_OUTPUT
echo "VERSION_TAG=latest" >> $GITHUB_ENV
else
git checkout "$VERSION"
echo "Using tag: $VERSION"
echo "BUILDING_LATEST=false" >> $GITHUB_ENV
echo "building_latest=false" >> $GITHUB_OUTPUT
echo "VERSION_TAG=$VERSION" >> $GITHUB_ENV
fi
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
# ──────────────────────────────────────────────
# Latest build path
# ──────────────────────────────────────────────
- name: Setup caching for build artifacts
if: env.BUILDING_LATEST == 'true'
uses: actions/cache@v4
id: cache-npm
with:
path: ~/.npm
key: npm-${{ runner.os }}-${{ hashFiles('${{ env.TEMP_DIR }}/ogx/docs/package-lock.json') }}
restore-keys: |
npm-${{ runner.os }}-
- name: Install dependencies and setup versioning
if: env.BUILDING_LATEST == 'true'
run: |
echo "Installing dependencies..."
cd "${{ env.TEMP_DIR }}/ogx/docs"
npm ci
echo "Dependencies installed"
echo "Setting up versioning configuration..."
# Copy persistent versionsArchived.json from repo
cp "${{ github.workspace }}/versionsArchived.json" ./
# Archived versions are served as standalone static HTML under docs/vX.Y.Z/
# Docusaurus versioning is not used - always write empty versions.json
echo "[]" > versions.json
# Fix GitHub org to match this repo's owner
sed -i "s|https://github.com/ogx-ai/ogx|https://github.com/${{ github.repository_owner }}/ogx|g" docusaurus.config.ts
# Restrict blog to top-level .md/.mdx files only (exclude subdirectory files)
node -e "
const fs = require('fs');
let c = fs.readFileSync('docusaurus.config.ts', 'utf8');
if (!c.match(/blog[\s\S]*?include:/)) {
c = c.replace(/(blog:\s*\{)/, \"\\\$1\\n include: ['*.{md,mdx}'],\");
fs.writeFileSync('docusaurus.config.ts', c);
console.log('Blog include pattern set to top-level only');
} else {
console.log('Blog already has explicit include pattern');
}
"
# Replace docsVersionDropdown with a custom dropdown populated from versionsArchived.json
node -e "
const fs = require('fs');
const archived = JSON.parse(fs.readFileSync('versionsArchived.json', 'utf8'));
let c = fs.readFileSync('docusaurus.config.ts', 'utf8');
// Build dropdown items from archived versions
const items = Object.entries(archived).map(([tag, url]) =>
' { label: \"' + tag + '\", href: \"' + url + '\" }'
).join(',\n');
// Replace the docsVersionDropdown block with a custom dropdown
c = c.replace(
/\{\s*type:\s*'docsVersionDropdown'[\s\S]*?\n\s{8}\},\n/,
'{\n' +
' type: \"dropdown\",\n' +
' label: \"main (unreleased)\",\n' +
' position: \"right\",\n' +
' items: [\n' +
items + ',\n' +
' { to: \"/versions\", label: \"All versions\" },\n' +
' ],\n' +
' },\n'
);
fs.writeFileSync('docusaurus.config.ts', c);
console.log('Version dropdown patched with ' + Object.keys(archived).length + ' archived versions');
"
echo "Configuration patched"
- name: Cache stable API docs
if: env.BUILDING_LATEST == 'true'
uses: actions/cache@v4
id: cache-api-stable
with:
path: ${{ env.TEMP_DIR }}/ogx/docs/docs/api
key: api-stable-${{ hashFiles('${{ env.TEMP_DIR }}/ogx/docs/static/ogx-spec.yaml') }}
restore-keys: api-stable-
- name: Cache experimental API docs
if: env.BUILDING_LATEST == 'true'
uses: actions/cache@v4
id: cache-api-experimental
with:
path: ${{ env.TEMP_DIR }}/ogx/docs/docs/api-experimental
key: api-experimental-${{ hashFiles('${{ env.TEMP_DIR }}/ogx/docs/static/experimental-ogx-spec.yaml') }}
restore-keys: api-experimental-
- name: Cache deprecated API docs
if: env.BUILDING_LATEST == 'true'
uses: actions/cache@v4
id: cache-api-deprecated
with:
path: ${{ env.TEMP_DIR }}/ogx/docs/docs/api-deprecated
key: api-deprecated-${{ hashFiles('${{ env.TEMP_DIR }}/ogx/docs/static/deprecated-ogx-spec.yaml') }}
restore-keys: api-deprecated-
- name: Generate API docs
if: env.BUILDING_LATEST == 'true'
run: |
cd "${{ env.TEMP_DIR }}/ogx/docs"
echo "Generating API docs in parallel..."
PIDS=()
if [ "${{ steps.cache-api-stable.outputs.cache-hit }}" != 'true' ]; then
npm run gen-api-docs stable &
PIDS+=($!)
fi
if [ "${{ steps.cache-api-experimental.outputs.cache-hit }}" != 'true' ]; then
npm run gen-api-docs experimental &
PIDS+=($!)
fi
if [ "${{ steps.cache-api-deprecated.outputs.cache-hit }}" != 'true' ]; then
npm run gen-api-docs deprecated &
PIDS+=($!)
fi
for pid in "${PIDS[@]}"; do
wait $pid || exit 1
done
echo "API docs generation completed"
- name: Build Docusaurus site
if: env.BUILDING_LATEST == 'true'
run: |
cd "${{ env.TEMP_DIR }}/ogx/docs"
# Patch out duplicate version badges from OpenAPI MDX files
find . -name "ogx-specification.info.mdx" -type f -exec sed -i '/<span$/,/<\/span>$/d' {} \;
echo "Running Docusaurus build..."
npm run build
echo "Docusaurus build completed"
env:
NODE_OPTIONS: "--max-old-space-size=10240"
- name: Deploy latest build to docs/
if: env.BUILDING_LATEST == 'true'
run: |
DOCS_DIR="${{ github.workspace }}/docs"
# Clear everything except .git, .nojekyll, and archived versions (static HTML under v*)
find "$DOCS_DIR" -mindepth 1 -maxdepth 1 ! -name '.git' ! -name '.nojekyll' ! -name 'v[0-9]*' -exec rm -rf {} +
# Copy Docusaurus build output
cp -r "${{ env.TEMP_DIR }}/ogx/docs/build/"* "$DOCS_DIR/"
# Copy versioning files
cp "${{ github.workspace }}/versionsArchived.json" "$DOCS_DIR/"
echo "[]" > "$DOCS_DIR/versions.json"
touch "$DOCS_DIR/.nojekyll"
echo "Latest build deployed to docs/"
# ──────────────────────────────────────────────
# Versioned (archived) build path
# ──────────────────────────────────────────────
- name: Build archived version
if: env.BUILDING_LATEST != 'true'
run: |
./build-archived-version.sh "${{ env.VERSION_TAG }}" --ogx-dir "${{ env.TEMP_DIR }}/ogx"
- name: Update versionsArchived.json
if: env.BUILDING_LATEST != 'true'
run: |
TAG="${{ env.VERSION_TAG }}"
python3 -c "
import json
with open('versionsArchived.json') as f:
archived = json.load(f)
tag = '${TAG}'
url = 'https://ogx-ai.github.io/${TAG}/'
if tag not in archived:
archived[tag] = url
def version_key(item):
parts = item[0].lstrip('v').split('.')
return [int(p) for p in parts if p.isdigit()]
archived = dict(sorted(archived.items(), key=version_key, reverse=True))
with open('versionsArchived.json', 'w') as f:
json.dump(archived, f, indent=2)
f.write('\n')
"
# Also update the deployed copy
cp versionsArchived.json docs/
- name: Commit archived version
if: env.BUILDING_LATEST != 'true'
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add -f "docs/${{ env.VERSION_TAG }}/" versionsArchived.json docs/versionsArchived.json
git diff --staged --quiet || git commit -s -m "docs: add archived version ${{ env.VERSION_TAG }}"
git pull --rebase origin main
git push
# ──────────────────────────────────────────────
# Common: verify and upload Pages artifact
# ──────────────────────────────────────────────
- name: Verify deployment structure
run: |
echo "Contents of docs directory:"
ls -la "${{ github.workspace }}/docs/" | head -10
echo -e "\nVersioning files:"
[ -f "${{ github.workspace }}/docs/versionsArchived.json" ] && echo "versionsArchived.json exists" || echo "versionsArchived.json missing"
- name: Setup GitHub Pages
if: ${{ (github.event.inputs.action == 'build-and-deploy' || github.event.inputs.action == '' || github.event_name == 'repository_dispatch') && (env.BUILDING_LATEST == 'true' || github.event_name != 'repository_dispatch') }}
uses: actions/configure-pages@v5
- name: Upload Pages artifact
if: ${{ (github.event.inputs.action == 'build-and-deploy' || github.event.inputs.action == '' || github.event_name == 'repository_dispatch') && (env.BUILDING_LATEST == 'true' || github.event_name != 'repository_dispatch') }}
uses: actions/upload-pages-artifact@v3
with:
path: 'docs'
deploy:
if: ${{ (github.event.inputs.action == 'build-and-deploy' || github.event.inputs.action == '' || github.event_name == 'repository_dispatch') && needs.build.outputs.building_latest != 'false' }}
runs-on: ubuntu-latest
needs: build
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
rebuild-latest:
# After committing an archived version, trigger a full latest rebuild so the
# Pages deployment includes both the main site and all archived versions.
if: ${{ needs.build.outputs.building_latest == 'false' }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Trigger latest docs rebuild
uses: peter-evans/repository-dispatch@v3
with:
event-type: docs-update
deploy-only:
if: ${{ github.event.inputs.action == 'deploy-only' }}
runs-on: ubuntu-latest
permissions:
contents: read
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup GitHub Pages
uses: actions/configure-pages@v5
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: 'docs'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4