Deploy Documentation #747
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: Deploy Documentation | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| subfolder: | |
| description: 'Subfolder for documentation. Defaults to "docs", leave empty for root deployment' | |
| required: false | |
| default: '' | |
| type: string | |
| triggering_pr_number: | |
| description: 'PR number that triggered this deployment' | |
| required: false | |
| default: '' | |
| type: string | |
| triggering_pr_title: | |
| description: 'PR title that triggered this deployment' | |
| required: false | |
| default: '' | |
| type: string | |
| triggering_commit_sha: | |
| description: 'Commit SHA that triggered this deployment' | |
| required: false | |
| default: '' | |
| type: string | |
| triggering_branch: | |
| description: 'Branch that triggered this deployment' | |
| required: false | |
| default: '' | |
| type: string | |
| original_pr_number: | |
| description: 'Original PR number (if different from triggering PR)' | |
| required: false | |
| default: '' | |
| type: string | |
| # Ensure only latest deployment runs | |
| concurrency: | |
| group: docs-deployment | |
| cancel-in-progress: true | |
| jobs: | |
| merge-docs: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Log deployment trigger information | |
| run: | | |
| echo "๐ Starting documentation deployment" | |
| echo "๐ Trigger Information:" | |
| echo " - Branch: ${{ inputs.triggering_branch || 'N/A' }}" | |
| echo " - Commit: ${{ inputs.triggering_commit_sha || 'N/A' }}" | |
| if [ -n "${{ inputs.triggering_pr_number }}" ]; then | |
| echo " - PR: #${{ inputs.triggering_pr_number }} - ${{ inputs.triggering_pr_title }}" | |
| if [ -n "${{ inputs.original_pr_number }}" ] && [ "${{ inputs.original_pr_number }}" != "${{ inputs.triggering_pr_number }}" ]; then | |
| echo " - Original PR: #${{ inputs.original_pr_number }} (cherry-picked)" | |
| fi | |
| else | |
| echo " - PR: N/A (direct push)" | |
| fi | |
| echo " - Timestamp: $(date)" | |
| echo " - Workflow Run: ${{ github.run_id }}" | |
| echo " - Subfolder: ${{ inputs.subfolder || '(root deployment)' }}" | |
| - name: Checkout production branch | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: production | |
| token: ${{ secrets.ORG_GH_TOKEN }} | |
| fetch-depth: 0 # Fetch all history for all branches | |
| - name: Set up Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.9' | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| # Add any additional dependencies if needed | |
| - name: Read branches config | |
| id: config | |
| run: | | |
| if [ ! -f "branches-config.json" ]; then | |
| echo "โ branches-config.json not found!" | |
| exit 1 | |
| fi | |
| echo "โ Found branches-config.json" | |
| cat branches-config.json | |
| - name: Cleanup old version folders and assets | |
| run: | | |
| echo "๐งน Cleaning up all content except essential files..." | |
| # Define folders to keep (whitelist) | |
| keep_folders=( | |
| ".github" | |
| ".git" | |
| ".devcontainer" | |
| "scripts" | |
| ".vale" | |
| ".probe" | |
| ) | |
| # Define files to keep (whitelist) | |
| keep_files=( | |
| "branches-config.json" | |
| ".gitignore" | |
| "README.md" | |
| ".vale.ini" | |
| ) | |
| echo "๐ Folders to keep: ${keep_folders[*]}" | |
| echo "๐ Files to keep: ${keep_files[*]}" | |
| # Remove all directories except the ones we want to keep | |
| echo "๐๏ธ Removing old directories..." | |
| for dir in */; do | |
| if [ -d "$dir" ]; then | |
| dir_name=${dir%/} # Remove trailing slash | |
| should_keep=false | |
| for keep_folder in "${keep_folders[@]}"; do | |
| if [ "$dir_name" = "$keep_folder" ]; then | |
| should_keep=true | |
| break | |
| fi | |
| done | |
| if [ "$should_keep" = false ]; then | |
| echo "๐๏ธ Removing directory: $dir_name/" | |
| rm -rf "$dir" | |
| else | |
| echo "๐ Keeping essential directory: $dir_name/" | |
| fi | |
| fi | |
| done | |
| # Remove all files except the ones we want to keep | |
| echo "๐๏ธ Removing old files..." | |
| for file in *; do | |
| if [ -f "$file" ]; then | |
| should_keep=false | |
| for keep_file in "${keep_files[@]}"; do | |
| if [ "$file" = "$keep_file" ]; then | |
| should_keep=true | |
| break | |
| fi | |
| done | |
| if [ "$should_keep" = false ]; then | |
| echo "๐๏ธ Removing file: $file" | |
| rm -f "$file" | |
| else | |
| echo "๐ Keeping essential file: $file" | |
| fi | |
| fi | |
| done | |
| echo "โ Cleanup completed!" | |
| echo "๐ Remaining files after cleanup:" | |
| ls -la | grep -E "^[d-]" | head -10 | |
| - name: Clone and organize branches | |
| run: | | |
| set -e | |
| echo "๐ Starting branch cloning and organization..." | |
| # Read the branches config and extract branch information | |
| branches=$(python3 -c "import json; config=json.load(open('branches-config.json')); [print(f\"{v.get('sourceFolder','')}:{v.get('branch','main')}\") for v in config.get('versions',[]) if v.get('sourceFolder','')]") | |
| echo "๐ Branches to process:" | |
| echo "$branches" | |
| # Clone each branch into its respective folder | |
| for branch_info in $branches; do | |
| if [ -n "$branch_info" ]; then | |
| folder=$(echo $branch_info | cut -d':' -f1) | |
| branch=$(echo $branch_info | cut -d':' -f2) | |
| echo "๐ Processing $folder from branch $branch..." | |
| # Remove existing folder if it exists | |
| if [ -d "$folder" ]; then | |
| echo "๐๏ธ Removing existing $folder/" | |
| rm -rf "$folder" | |
| fi | |
| # Create temporary directory for this branch | |
| temp_dir="temp_$folder" | |
| # Clone the specific branch | |
| echo "โฌ๏ธ Cloning branch $branch into $temp_dir..." | |
| git clone --single-branch --branch "$branch" --depth 1 \ | |
| "https://github.com/${{ github.repository }}.git" "$temp_dir" | |
| # Move the contents (excluding .git) to the target folder | |
| mkdir -p "$folder" | |
| echo "๐ Moving contents from $temp_dir to $folder..." | |
| # Copy documentation content only, excluding development/build files | |
| # Excluded: .git, scripts/, branches-config.json, .github/, README.md, .gitignore, .devcontainer/, .probe | |
| find "$temp_dir" -mindepth 1 -maxdepth 1 \ | |
| ! -name '.git' \ | |
| ! -name 'scripts' \ | |
| ! -name 'branches-config.json' \ | |
| ! -name '.github' \ | |
| ! -name 'README.md' \ | |
| ! -name '.gitignore' \ | |
| ! -name '.devcontainer' \ | |
| ! -name '.probe' \ | |
| -exec cp -r {} "$folder/" \; | |
| # Clean up temp directory | |
| rm -rf "$temp_dir" | |
| echo "โ Successfully organized $folder from branch $branch" | |
| # Show what was copied | |
| echo "๐ Contents of $folder:" | |
| ls -la "$folder/" | head -10 | |
| fi | |
| done | |
| echo "๐ All branches cloned and organized!" | |
| - name: Run docs merger | |
| run: | | |
| echo "๐ Running documentation merger..." | |
| # Get subfolder from input (no fallback - empty means root deployment) | |
| SUBFOLDER="${{ inputs.subfolder }}" | |
| echo "๐ Using subfolder: '$SUBFOLDER'" | |
| # Run the merge script with branches config | |
| if [ -n "$SUBFOLDER" ]; then | |
| echo "๐ Deploying to subfolder: $SUBFOLDER" | |
| python3 scripts/merge_docs_configs.py \ | |
| --branches-config branches-config.json \ | |
| --base-dir . \ | |
| --subfolder "$SUBFOLDER" \ | |
| --output docs.json | |
| else | |
| echo "๐ Deploying to root (no subfolder)" | |
| python3 scripts/merge_docs_configs.py \ | |
| --branches-config branches-config.json \ | |
| --base-dir . \ | |
| --output docs.json | |
| fi | |
| echo "โ Documentation merge completed!" | |
| - name: Cleanup cloned version folders | |
| run: | | |
| echo "๐งน Cleaning up temporary cloned version folders..." | |
| # Get current version folders from config | |
| current_folders=$(python3 -c "import json; config=json.load(open('branches-config.json')); folders=[v.get('sourceFolder','') for v in config.get('versions',[]) if v.get('sourceFolder','')]; print(' '.join(folders))") | |
| echo "๐ Removing cloned folders: $current_folders" | |
| # Remove the temporary cloned folders (they've been processed into subfolder structure) | |
| for folder in $current_folders; do | |
| if [ -n "$folder" ] && [ -d "$folder" ]; then | |
| echo "๐๏ธ Removing cloned folder: $folder/" | |
| rm -rf "$folder" | |
| fi | |
| done | |
| echo "โ Cleanup of cloned folders completed!" | |
| - name: Add canonical URLs to MDX files | |
| run: | | |
| echo "๐งฉ Running canonical URL update script..." | |
| python3 scripts/add-canonical-urls/index.py || { echo "โ Canonical script failed"; exit 1; } | |
| echo "โ Canonical URL update completed." | |
| - name: Verify output | |
| run: | | |
| echo "๐ Checking generated files..." | |
| if [ -f "docs.json" ]; then | |
| echo "โ docs.json generated successfully" | |
| echo "๐ docs.json size: $(wc -c < docs.json) bytes" | |
| echo "๐ First few lines of docs.json:" | |
| head -20 docs.json | |
| else | |
| echo "โ docs.json not found!" | |
| exit 1 | |
| fi | |
| echo "" | |
| echo "๐ Generated file structure:" | |
| find . -name "*.mdx" -o -name "*.md" -o -name "*.json" -o -name "*.css" -o -name "*.png" | head -20 | |
| - name: Close previous deployment PRs | |
| run: | | |
| echo "๐ Finding and closing previous deployment PRs..." | |
| # Find PRs that match BOTH criteria: | |
| # 1. Have the "auto-deployment" label | |
| # 2. Branch starts with "docs-merge-" | |
| DEPLOYMENT_PRS=$(gh pr list \ | |
| --state open \ | |
| --label "auto-deployment" \ | |
| --json number,headRefName,labels \ | |
| --jq '.[] | select(.headRefName | startswith("docs-merge-")) | .number') | |
| if [ -n "$DEPLOYMENT_PRS" ]; then | |
| echo "๐ Found deployment PRs to close: $DEPLOYMENT_PRS" | |
| for pr_number in $DEPLOYMENT_PRS; do | |
| echo "โ Closing deployment PR #$pr_number" | |
| gh pr close "$pr_number" \ | |
| --comment "๐ค Superseded by newer deployment (Run #${{ github.run_number }})" \ | |
| || echo "โ ๏ธ Failed to close PR #$pr_number (may already be closed)" | |
| done | |
| echo "โ Closed all previous deployment PRs" | |
| else | |
| echo "โ No deployment PRs found to close" | |
| fi | |
| env: | |
| GH_TOKEN: ${{ secrets.ORG_GH_TOKEN }} | |
| - name: Create Pull Request | |
| id: create-pr | |
| uses: peter-evans/create-pull-request@v7 | |
| with: | |
| token: ${{ secrets.ORG_GH_TOKEN }} | |
| branch: docs-merge-${{ github.run_number }} | |
| base: production | |
| title: "๐ค Auto-merge documentation from branches" | |
| body: | | |
| ## ๐ Documentation Merge Summary | |
| This PR contains automatically merged documentation from multiple branches. | |
| **Triggered by:** | |
| - **Branch:** ${{ inputs.triggering_branch || 'N/A' }} | |
| - **Commit:** ${{ inputs.triggering_commit_sha || 'N/A' }} | |
| - **PR:** ${{ inputs.triggering_pr_number && format('#{0} - {1}', inputs.triggering_pr_number, inputs.triggering_pr_title) || 'N/A (direct push)' }}${{ inputs.original_pr_number && inputs.original_pr_number != inputs.triggering_pr_number && format(' (cherry-pick of #{0})', inputs.original_pr_number) || '' }} | |
| **Deployment Details:** | |
| - **Generated from:** `branches-config.json` | |
| - **Run ID:** ${{ github.run_id }} | |
| - **Subfolder:** `${{ inputs.subfolder || '(root deployment)' }}` | |
| - **Timestamp:** $(date) | |
| ### Changes Include: | |
| - โ Merged documentation from multiple branches | |
| - โ Generated unified `docs.json` configuration | |
| - โ Updated assets and content structure | |
| - โ Cleaned up outdated version folders | |
| --- | |
| ๐ฆ **This PR will be processed by merge queue to ensure proper validation and ordering.** | |
| Previous deployment PRs have been automatically closed to prevent conflicts. | |
| labels: | | |
| documentation | |
| auto-deployment | |
| automated | |
| commit-message: | | |
| ๐ค Auto-merge documentation from branches | |
| Generated from branches-config.json at ${{ github.event.head_commit.timestamp }} | |
| - Merged documentation from multiple branches | |
| - Generated unified docs.json | |
| - Updated assets and content structure | |
| delete-branch: true | |
| draft: false | |
| maintainer-can-modify: true | |
| author: ${{ github.actor }} <${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com> | |
| committer: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> | |
| - name: Enable auto-merge on deployment PR | |
| if: steps.create-pr.outputs.pull-request-number | |
| run: | | |
| PR_NUMBER="${{ steps.create-pr.outputs.pull-request-number }}" | |
| echo "๏ฟฝ Enabling auto-merge on deployment PR #$PR_NUMBER..." | |
| gh pr merge --squash --auto "$PR_NUMBER" | |
| echo "โ Auto-merge enabled on PR #$PR_NUMBER" | |
| env: | |
| GH_TOKEN: ${{ secrets.ORG_GH_TOKEN }} | |
| - name: Create deployment summary | |
| run: | | |
| echo "## ๐ Documentation Deployment Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### ๐ Trigger Information" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Branch:** ${{ inputs.triggering_branch || 'N/A' }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Commit:** ${{ inputs.triggering_commit_sha || 'N/A' }}" >> $GITHUB_STEP_SUMMARY | |
| if [ -n "${{ inputs.triggering_pr_number }}" ]; then | |
| echo "- **PR:** #${{ inputs.triggering_pr_number }} - ${{ inputs.triggering_pr_title }}" >> $GITHUB_STEP_SUMMARY | |
| if [ -n "${{ inputs.original_pr_number }}" ] && [ "${{ inputs.original_pr_number }}" != "${{ inputs.triggering_pr_number }}" ]; then | |
| echo "- **Original PR:** #${{ inputs.original_pr_number }} (cherry-picked)" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| else | |
| echo "- **PR:** N/A (direct push)" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### โ Successfully merged documentation" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Generated files:**" >> $GITHUB_STEP_SUMMARY | |
| echo "- \`docs.json\` - Unified configuration" >> $GITHUB_STEP_SUMMARY | |
| if [ -f "docs.json" ]; then | |
| echo "- Asset files (favicon.png, style.css, images/, etc.)" >> $GITHUB_STEP_SUMMARY | |
| echo "- Version folders with documentation content" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Timestamp:** $(date)" >> $GITHUB_STEP_SUMMARY |