docs-update #174
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |