Skip to content

Build and Deploy Docusaurus Documentation #9

Build and Deploy Docusaurus Documentation

Build and Deploy Docusaurus Documentation #9

name: Build and Deploy Docusaurus Documentation
on:
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
permissions:
contents: write
pages: write
id-token: write
jobs:
build:
if: ${{ github.event.inputs.action != 'deploy-only' }}
runs-on: ubuntu-latest
steps:
- name: Checkout this repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Clone llama-stack repository
run: |
echo "📥 Cloning llama-stack repository..."
TEMP_DIR=$(mktemp -d)
echo "TEMP_DIR=$TEMP_DIR" >> $GITHUB_ENV
git clone https://github.com/llamastack/llama-stack.git "$TEMP_DIR/llama-stack"
cd "$TEMP_DIR/llama-stack"
git fetch --all --tags
# Determine version to checkout
VERSION="${{ github.event.inputs.version }}"
if [ "$VERSION" = "latest" ] || [ -z "$VERSION" ]; then
git checkout main
echo "✅ Using main branch (latest)"
echo "BUILDING_LATEST=true" >> $GITHUB_ENV
echo "VERSION_TAG=latest" >> $GITHUB_ENV
else
git checkout "$VERSION"
echo "✅ Using tag: $VERSION"
echo "BUILDING_LATEST=false" >> $GITHUB_ENV
echo "VERSION_TAG=$VERSION" >> $GITHUB_ENV
fi
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies and setup versioning
run: |
echo "📦 Installing dependencies..."
cd "${{ env.TEMP_DIR }}/llama-stack/docs"
npm ci
echo "✅ Dependencies installed"
echo "⚙️ Setting up versioning configuration..."
# Copy persistent versionsArchived.json from repo
cp "${{ github.workspace }}/versionsArchived.json" ./
# Load existing versions.json from deployed site or create empty
if [ -f "${{ github.workspace }}/docs/versions.json" ]; then
# If we're building a specific version, exclude it from the imported versions.json
if [ "${{ env.BUILDING_LATEST }}" != "true" ]; then
# Filter out the version we're about to build
node -e "
const versions = JSON.parse(require('fs').readFileSync('${{ github.workspace }}/docs/versions.json', 'utf8'));
const filtered = versions.filter(v => v !== '${{ env.VERSION_TAG }}');
require('fs').writeFileSync('versions.json', JSON.stringify(filtered, null, 2));
console.log('✅ Loaded versions.json (filtered out ${{ env.VERSION_TAG }})');
"
else
cp "${{ github.workspace }}/docs/versions.json" ./
echo "✅ Loaded existing versions.json"
fi
else
echo "[]" > versions.json
echo "✅ Created empty versions.json"
fi
# Patch Docusaurus config for versioning
node << 'EOF'
const fs = require('fs');
let config = fs.readFileSync('docusaurus.config.ts', 'utf8');
// Add versioning imports after OpenAPI import
const versioningImports = `
// Import fs for versioning configuration
const fs = require('fs');
// Versioning configuration for llamastack.github.io
const versionsArchived = (() => {
try {
return JSON.parse(fs.readFileSync('./versionsArchived.json', 'utf8'));
} catch (e) {
console.warn('Could not load versionsArchived.json:', e);
return {};
}
})();
const archivedVersionsDropdownItems = Object.entries(versionsArchived).map(
([versionName, versionUrl]) => ({
label: versionName,
href: versionUrl,
})
);
`;
config = config.replace(
/import type \* as OpenApiPlugin from "docusaurus-plugin-openapi-docs";/,
`import type * as OpenApiPlugin from "docusaurus-plugin-openapi-docs";
${versioningImports}`
);
// Add version dropdown to navbar (replace GitHub item)
const versionDropdown = ` {
href: 'https://github.com/llamastack/llama-stack',
label: 'GitHub',
position: 'right',
},
{
type: 'docsVersionDropdown',
position: 'right',
dropdownItemsAfter: archivedVersionsDropdownItems.length > 0 ? [
{
type: 'html',
value: '<hr class="dropdown-separator">',
},
{
type: 'html',
className: 'dropdown-archived-versions',
value: '<b>Previous versions</b>',
},
...archivedVersionsDropdownItems,
] : [],
},`;
config = config.replace(
/\s*{\s*href:\s*'https:\/\/github\.com\/llamastack\/llama-stack',\s*label:\s*'GitHub',\s*position:\s*'right',\s*},/,
versionDropdown
);
fs.writeFileSync('docusaurus.config.ts', config);
console.log('✅ Configuration patched');
EOF
echo "✅ Configuration patches applied"
- name: Import existing versioning artifacts
run: |
echo "📥 Importing existing versioning artifacts from repository..."
cd "${{ env.TEMP_DIR }}/llama-stack/docs"
# Copy existing versioned_docs if they exist
if [ -d "${{ github.workspace }}/versioned_docs" ]; then
cp -r "${{ github.workspace }}/versioned_docs" ./
echo "✅ Imported existing versioned_docs"
else
echo "ℹ️ No existing versioned_docs found (first version)"
fi
# Copy existing versioned_sidebars if they exist
if [ -d "${{ github.workspace }}/versioned_sidebars" ]; then
cp -r "${{ github.workspace }}/versioned_sidebars" ./
echo "✅ Imported existing versioned_sidebars"
else
echo "ℹ️ No existing versioned_sidebars found (first version)"
fi
# Copy existing versions.json if it exists (overrides what we loaded earlier)
if [ -f "${{ github.workspace }}/versions.json" ]; then
cp "${{ github.workspace }}/versions.json" ./
echo "✅ Imported existing versions.json"
else
echo "ℹ️ No existing versions.json found (first version)"
fi
echo "✅ Versioning artifacts import completed"
- name: Build documentation
run: |
cd "${{ env.TEMP_DIR }}/llama-stack/docs"
# Generate API docs first (required for current build)
npm run gen-api-docs all
echo "✅ API docs generated"
# Create version if not latest (after content is ready)
if [ "${{ env.BUILDING_LATEST }}" != "true" ]; then
echo "📚 Creating Docusaurus version: ${{ env.VERSION_TAG }}"
# Create the version snapshot
npx docusaurus docs:version "${{ env.VERSION_TAG }}"
# Ensure prompt-format.png is available where versioned docs expect it
mkdir -p versioned_docs/resources
if [ ! -f "versioned_docs/resources/prompt-format.png" ]; then
echo "📥 Downloading missing prompt-format.png..."
curl -o versioned_docs/resources/prompt-format.png https://raw.githubusercontent.com/llamastack/llama-stack/main/docs/static/img/prompt-format.png
echo "✅ Downloaded prompt-format.png to versioned_docs/resources/"
else
echo "✅ prompt-format.png already exists in versioned_docs/resources/"
fi
echo "✅ Version ${{ env.VERSION_TAG }} created"
else
echo "🏗️ Building latest version (no version snapshot needed)"
fi
- name: Build Docusaurus site
run: |
echo "🏗️ Building Docusaurus site..."
cd "${{ env.TEMP_DIR }}/llama-stack/docs"
# Generate API docs for current build
npm run gen-api-docs all
# Patch out duplicate version badges from OpenAPI MDX files
echo "🔧 Patching out duplicate version badges..."
find . -name "llama-stack-specification.info.mdx" -type f -exec sed -i '/<span$/,/<\/span>$/d' {} \;
# Also patch versioned files if they exist
if [ -d "versioned_docs" ]; then
find versioned_docs -name "llama-stack-specification.info.mdx" -type f -exec sed -i '/<span$/,/<\/span>$/d' {} \;
fi
echo "✅ Version badge patching completed"
# Build the site
npm run build
echo "✅ Docusaurus build completed"
- name: Deploy to GitHub Pages
run: |
echo "🗂️ Deploying Docusaurus build..."
DOCS_DIR="${{ github.workspace }}/docs"
# Smart deployment: clear everything except .git, .nojekyll, and archived versions
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 }}/llama-stack/docs/build/"* "$DOCS_DIR/"
# Ensure .nojekyll exists
touch "$DOCS_DIR/.nojekyll"
echo "✅ Docusaurus content deployed"
- name: Update workspace artifacts
if: env.BUILDING_LATEST != 'true'
run: |
echo "📋 Updating workspace versioning artifacts..."
BUILD_PATH="${{ env.TEMP_DIR }}/llama-stack/docs"
# Copy versioned docs and sidebars to workspace (for git commit)
if [ -d "$BUILD_PATH/versioned_docs" ]; then
cp -r "$BUILD_PATH/versioned_docs" "${{ github.workspace }}/"
echo "✅ Copied versioned_docs to workspace"
fi
if [ -d "$BUILD_PATH/versioned_sidebars" ]; then
cp -r "$BUILD_PATH/versioned_sidebars" "${{ github.workspace }}/"
echo "✅ Copied versioned_sidebars to workspace"
fi
# Copy updated versions.json to workspace
cp "$BUILD_PATH/versions.json" "${{ github.workspace }}/"
echo "✅ Updated workspace versions.json"
- name: Setup versioning files in deployed site
run: |
echo "⚙️ Setting up versioning configuration files..."
BUILD_PATH="${{ env.TEMP_DIR }}/llama-stack/docs"
# Copy versioning files to deployment
cp "$BUILD_PATH/versionsArchived.json" "${{ github.workspace }}/docs/"
cp "$BUILD_PATH/versions.json" "${{ github.workspace }}/docs/"
echo "✅ Versioning files created"
- name: Verify deployment structure
run: |
echo "🔍 Verifying deployment structure..."
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"
[ -f "${{ github.workspace }}/docs/versions.json" ] && echo "✅ versions.json exists" || echo "❌ versions.json missing"
echo -e "\n✅ Structure verification complete"
- name: Commit versioning artifacts
if: env.BUILDING_LATEST != 'true'
run: |
echo "💾 Committing versioning artifacts..."
cd "${{ github.workspace }}"
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
# Add versioning artifacts
git add versioned_docs/ versioned_sidebars/ versions.json 2>/dev/null || true
# Add deployment
git add docs/
# Commit if there are changes
if ! git diff --staged --quiet; then
git commit -m "Add Docusaurus version ${{ env.VERSION_TAG }}
- Created version snapshot in versioned_docs/version-${{ env.VERSION_TAG }}/
- Updated versions.json with new version
- Built and deployed multi-version site
🤖 Generated by Docusaurus versioning workflow"
git push
echo "✅ Changes committed and pushed"
else
echo "ℹ️ No changes to commit"
fi
- name: Setup GitHub Pages
if: ${{ github.event.inputs.action == 'build-and-deploy' }}
uses: actions/configure-pages@v5
- name: Upload Pages artifact
if: ${{ github.event.inputs.action == 'build-and-deploy' }}
uses: actions/upload-pages-artifact@v3
with:
path: 'docs'
deploy:
if: ${{ github.event.inputs.action == 'build-and-deploy' }}
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
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