Skip to content

Fix CLI reference documentation issues #216

Fix CLI reference documentation issues

Fix CLI reference documentation issues #216

# .github/workflows/apply-overlays-and-regenerate.yml
#
# This workflow runs in the seqeralabs/docs repository
# Phase 3: Applies approved overlays and regenerates documentation
name: Apply Overlays and Regenerate Docs
on:
pull_request:
types: [labeled]
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to process'
required: true
type: number
jobs:
apply-and-regenerate:
runs-on: ubuntu-latest
if: |
(github.event_name == 'pull_request' && github.event.label.name == 'overlays-approved') ||
github.event_name == 'workflow_dispatch'
steps:
- name: Get PR branch name
id: pr_branch
uses: actions/github-script@v7
with:
script: |
let branchName;
if (context.eventName === 'pull_request') {
branchName = context.payload.pull_request.head.ref;
} else {
// workflow_dispatch - get branch from PR number
const pr = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: ${{ github.event.inputs.pr_number }}
});
branchName = pr.data.head.ref;
}
core.setOutput('branch', branchName);
return branchName;
- name: Checkout PR branch
uses: actions/checkout@v4
with:
ref: ${{ steps.pr_branch.outputs.branch }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install Python dependencies
run: |
pip install pyyaml
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install Node dependencies
run: |
npm install
- name: Install Speakeasy CLI
run: |
curl -fsSL https://raw.githubusercontent.com/speakeasy-api/speakeasy/main/install.sh | sh
echo "$HOME/.speakeasy/bin" >> $GITHUB_PATH
- name: Detect version from specs directory
id: version
run: |
cd platform-api-docs/scripts/specs
# Find the latest base spec (highest version number) - exclude decorated specs
# Only match files like seqera-api-1.102.0.yaml (version numbers starting with digit)
# Support both .yaml and .yml extensions
# Sort by version number (not modification time)
LATEST_SPEC=$(ls seqera-api-[0-9]*.yaml seqera-api-[0-9]*.yml 2>/dev/null | \
sed -E 's/seqera-api-([0-9.]+)\.ya?ml/\1 &/' | \
sort -t. -k1,1n -k2,2n -k3,3n | \
tail -n 1 | \
cut -d' ' -f2)
if [ -z "$LATEST_SPEC" ]; then
echo "❌ Error: No base spec file found (pattern: seqera-api-[0-9]*.{yaml,yml})"
echo "Files in directory:"
ls -la
exit 1
fi
VERSION=$(echo "$LATEST_SPEC" | sed -E 's/seqera-api-(.*)\.ya?ml/\1/')
echo "api_version=$VERSION" >> $GITHUB_OUTPUT
echo "Detected API version: $VERSION from file: $LATEST_SPEC"
- name: Extract overlay files from markdown
run: |
cd platform-api-docs/scripts/specs
# Check if claude-generated-overlays.md exists
if [ ! -f "claude-generated-overlays.md" ]; then
echo "⚠️ No claude-generated-overlays.md found - skipping extraction"
exit 0
fi
# Extract YAML code blocks from markdown
python3 - <<'PYTHON_SCRIPT'
import re
from pathlib import Path
md_file = Path("claude-generated-overlays.md")
if not md_file.exists():
print("No markdown file found")
exit(0)
content = md_file.read_text()
# Pattern to match yaml/yml code blocks with optional filename labels
# Looks for: ```yaml or ```yml, then content until closing ```
# Uses non-greedy match and looks for ``` at start of line
pattern = r'```(?:yaml|yml)\s*\n(.*?)\n```'
# Also try to find filenames mentioned before code blocks
# Pattern: "filename.yaml" or **filename.yaml** or <!-- filename.yaml -->
filename_pattern = r'(?:^|\n)(?:#+\s*)?(?:\*\*)?([a-zA-Z0-9_-]+-overlay-[0-9.]+\.ya?ml)(?:\*\*)?'
blocks = re.finditer(pattern, content, re.MULTILINE | re.DOTALL)
extracted_count = 0
current_pos = 0
for block in blocks:
yaml_content = block.group(1).strip()
# Look backwards from this block to find a filename (use the LAST/closest match)
text_before = content[current_pos:block.start()]
filename_matches = re.findall(filename_pattern, text_before, re.MULTILINE | re.IGNORECASE)
if filename_matches:
# Take the last (closest) filename match
filename = filename_matches[-1]
# Normalize to .yaml extension
filename = re.sub(r'\.yml$', '.yaml', filename)
output_path = Path(filename)
output_path.write_text(yaml_content + '\n')
print(f"✅ Extracted: {filename}")
extracted_count += 1
else:
print(f"⚠️ Found YAML block but no filename at position {block.start()}")
current_pos = block.end()
if extracted_count > 0:
print(f"\n✅ Successfully extracted {extracted_count} overlay file(s)")
else:
print("⚠️ No overlay files extracted - check markdown format")
PYTHON_SCRIPT
echo "✅ Overlay extraction complete"
- name: Consolidate overlay files
run: |
cd platform-api-docs/scripts/specs
# List extracted overlay files for debugging
echo "=== Extracted overlay files ==="
ls -la *-overlay-${{ steps.version.outputs.api_version }}.yaml 2>/dev/null || echo "No .yaml overlays found"
ls -la *-overlay-${{ steps.version.outputs.api_version }}.yml 2>/dev/null || echo "No .yml overlays found"
# Create consolidated overlay
cat > all-changes-overlay-${{ steps.version.outputs.api_version }}.yaml <<'EOF'
overlay: 1.0.0
info:
title: Consolidated overlay for v${{ steps.version.outputs.api_version }}
version: 0.0.0
actions:
EOF
# Append version-specific overlays
echo " # ===== VERSION ${{ steps.version.outputs.api_version }} OVERLAYS =====" >> all-changes-overlay-${{ steps.version.outputs.api_version }}.yaml
# Track how many files we process
OVERLAY_COUNT=0
# Find and append all version-specific overlay files - support both .yaml and .yml
for overlay in *-overlay-${{ steps.version.outputs.api_version }}.yaml *-overlay-${{ steps.version.outputs.api_version }}.yml; do
if [ -f "$overlay" ] && [ "$overlay" != "all-changes-overlay-${{ steps.version.outputs.api_version }}.yaml" ]; then
echo "Adding $overlay to consolidated file"
sed -n '/^actions:/,$ p' "$overlay" | tail -n +2 >> all-changes-overlay-${{ steps.version.outputs.api_version }}.yaml
OVERLAY_COUNT=$((OVERLAY_COUNT + 1))
fi
done
echo "✅ Consolidated $OVERLAY_COUNT overlay files"
# Show first 30 lines of consolidated file for debugging
echo "=== First 30 lines of consolidated overlay ==="
head -n 30 all-changes-overlay-${{ steps.version.outputs.api_version }}.yaml
# Count action items
ACTION_COUNT=$(grep -c ' - target:' all-changes-overlay-${{ steps.version.outputs.api_version }}.yaml || echo "0")
echo "✅ Total action items: $ACTION_COUNT"
- name: Upload overlay artifacts on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: overlay-files-${{ steps.version.outputs.api_version }}
path: |
platform-api-docs/scripts/specs/*-overlay-${{ steps.version.outputs.api_version }}.yaml
platform-api-docs/scripts/specs/*-overlay-${{ steps.version.outputs.api_version }}.yml
retention-days: 7
if-no-files-found: warn
- name: Apply overlays to decorated spec
run: |
cd platform-api-docs/scripts/specs
# Detect decorated spec extension
if [ -f "seqera-api-latest-decorated.yaml" ]; then
DECORATED_SPEC="seqera-api-latest-decorated.yaml"
NEW_SPEC="seqera-api-latest-decorated-new.yaml"
elif [ -f "seqera-api-latest-decorated.yml" ]; then
DECORATED_SPEC="seqera-api-latest-decorated.yml"
NEW_SPEC="seqera-api-latest-decorated-new.yml"
else
echo "❌ Error: seqera-api-latest-decorated.yaml/yml not found"
exit 1
fi
# Apply consolidated overlay
speakeasy overlay apply \
-s "$DECORATED_SPEC" \
-o all-changes-overlay-${{ steps.version.outputs.api_version }}.yaml \
> "$NEW_SPEC"
# Replace old decorated spec
mv "$NEW_SPEC" "$DECORATED_SPEC"
echo "✅ Applied overlays to decorated spec"
- name: Validate decorated spec
run: |
cd platform-api-docs/scripts/specs
# Detect decorated spec extension
if [ -f "seqera-api-latest-decorated.yaml" ]; then
DECORATED_SPEC="seqera-api-latest-decorated.yaml"
elif [ -f "seqera-api-latest-decorated.yml" ]; then
DECORATED_SPEC="seqera-api-latest-decorated.yml"
else
echo "❌ Error: seqera-api-latest-decorated.yaml/yml not found"
exit 1
fi
# Run validation and capture output to file to avoid overwhelming logs
echo "Running OpenAPI validation..."
if speakeasy validate openapi -s "$DECORATED_SPEC" > validation-output.txt 2>&1; then
echo "✅ Decorated spec is valid"
# Show summary of any hints
HINT_COUNT=$(grep -c "validation hint:" validation-output.txt 2>/dev/null || echo "0")
echo " ($HINT_COUNT hints suppressed - mostly missing examples)"
else
echo "⚠️ Validation completed with issues"
# Check for actual errors vs just hints
ERROR_COUNT=$(grep -c "ERROR" validation-output.txt 2>/dev/null || echo "0")
WARN_COUNT=$(grep -c "WARN" validation-output.txt 2>/dev/null || echo "0")
HINT_COUNT=$(grep -c "validation hint:" validation-output.txt 2>/dev/null || echo "0")
echo " Errors: $ERROR_COUNT"
echo " Warnings: $WARN_COUNT"
echo " Hints: $HINT_COUNT"
# Show actual errors if any
if [ "$ERROR_COUNT" -gt 0 ]; then
echo ""
echo "Errors found:"
grep "ERROR" validation-output.txt | head -20
exit 1
fi
# If only hints/warnings, continue (non-critical)
echo " No critical errors - continuing workflow"
fi
# Clean up
rm -f validation-output.txt
- name: Update info page version
run: |
INFO_PAGE="platform-api-docs/docs/info/seqera-api.info.mdx"
# Update the version badge in the info page
sed -i.bak 's/children={"Version: [0-9.]*"}/children={"Version: ${{ steps.version.outputs.api_version }}"}/' "$INFO_PAGE"
rm -f "${INFO_PAGE}.bak"
echo "✅ Updated info page version to ${{ steps.version.outputs.api_version }}"
- name: Generate parameter tables
run: |
cd platform-api-docs/scripts
node extract-api-tables.mjs
echo "✅ Generated parameter tables for info pages"
- name: Clean existing API docs
run: |
npx docusaurus clean-api-docs platform
echo "✅ Cleaned existing API docs"
env:
EXCLUDE_MULTIQC: true
EXCLUDE_FUSION: true
EXCLUDE_WAVE: true
- name: Generate new API docs
run: |
npx docusaurus gen-api-docs platform
echo "✅ Generated new API documentation"
env:
EXCLUDE_MULTIQC: true
EXCLUDE_FUSION: true
EXCLUDE_WAVE: true
- name: Update sidebar with new operations
run: |
cd platform-api-docs/scripts/specs
# Check if analysis JSON exists
ANALYSIS_FILE=$(ls -t *-analysis.json 2>/dev/null | head -n 1)
if [ -n "$ANALYSIS_FILE" ]; then
python ../../../.claude/skills/openapi-overlay-generator/scripts/update_sidebar_v2.py \
../../docs/sidebar/sidebar.js \
"$ANALYSIS_FILE"
echo "✅ Updated sidebar with new operations"
else
echo "⚠️ No analysis file found - sidebar not updated"
fi
- name: Archive used overlays
run: |
cd platform-api-docs/scripts/specs
# Move version-specific overlays to archive
mkdir -p ../overlay_archives
# Archive both .yaml and .yml overlay files
for overlay in *-overlay-${{ steps.version.outputs.api_version }}.yaml *-overlay-${{ steps.version.outputs.api_version }}.yml; do
if [ -f "$overlay" ]; then
mv "$overlay" ../overlay_archives/
echo "Archived: $overlay"
fi
done
# Also archive comparison overlay - support both .yaml and .yml
for comparison in base-*-to-${{ steps.version.outputs.api_version }}-*.yaml base-*-to-${{ steps.version.outputs.api_version }}-*.yml; do
if [ -f "$comparison" ]; then
mv "$comparison" ../overlay_archives/
echo "Archived: $comparison"
fi
done
# Archive the claude-generated-overlays.md file
if [ -f "claude-generated-overlays.md" ]; then
mv claude-generated-overlays.md ../overlay_archives/
echo "Archived: claude-generated-overlays.md"
fi
# Archive analysis JSON files
for analysis in *-analysis.json; do
if [ -f "$analysis" ]; then
mv "$analysis" ../overlay_archives/
echo "Archived: $analysis"
fi
done
echo "✅ Archived overlays"
- name: Clean up old base specs
run: |
cd platform-api-docs/scripts/specs
# Keep only the latest 2 base specs (by version number) - support both .yaml and .yml
# Exclude decorated specs, sort by semantic version, delete all but newest 2
BASE_SPECS=$(ls seqera-api-[0-9]*.yaml seqera-api-[0-9]*.yml 2>/dev/null | \
sed -E 's/seqera-api-([0-9.]+)\.ya?ml/\1 &/' | \
sort -t. -k1,1n -k2,2n -k3,3n | \
cut -d' ' -f2)
if [ -n "$BASE_SPECS" ]; then
SPECS_TO_DELETE=$(echo "$BASE_SPECS" | head -n -2)
if [ -n "$SPECS_TO_DELETE" ]; then
echo "Deleting old base specs:"
echo "$SPECS_TO_DELETE"
echo "$SPECS_TO_DELETE" | xargs rm
else
echo "No old base specs to delete (keeping latest 2)"
fi
else
echo "No base specs found"
fi
echo "✅ Cleaned up old base specs"
- name: Commit changes
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add platform-api-docs/
git commit -m "Apply overlays and regenerate docs for v${{ steps.version.outputs.api_version }}" || echo "No changes to commit"
git push
- name: Update PR
uses: actions/github-script@v7
with:
script: |
const prNumber = context.payload.pull_request?.number || ${{ github.event.inputs.pr_number }};
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: `## ✅ Overlays Applied and Docs Regenerated
**API Version**: ${{ steps.version.outputs.api_version }}
### Changes Applied
- ✅ Consolidated overlays (permanent + version-specific)
- ✅ Applied to decorated spec
- ✅ Validated OpenAPI spec
- ✅ Generated parameter tables for info pages
- ✅ Regenerated MDX documentation files
- ✅ Updated sidebar with new operation entries
- ✅ Archived version-specific overlays
- ✅ Cleaned up old base specs
### Next Steps
1. **Review the generated documentation** - Check MDX files look correct
2. **Test locally** - Run \`npm run start\` to preview
3. **Request final review** - Mark PR ready for review
4. **Merge when approved** - Documentation will be published
---
*This PR is now ready for final review and approval.*`
});
// Remove draft status
await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
draft: false
});
- name: Create summary
run: |
echo "## 🎉 Documentation Update Complete!" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**API Version**: ${{ steps.version.outputs.api_version }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "All overlay files have been applied and documentation has been regenerated." >> $GITHUB_STEP_SUMMARY
echo "The PR is now ready for final review." >> $GITHUB_STEP_SUMMARY