Skip to content

Build static API

Build static API #732

Workflow file for this run

name: Build static API
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: static-api-${{ github.ref }}
cancel-in-progress: true
on:
push:
branches: [main, master]
paths:
- 'src/**'
- 'data/**'
- 'public/**'
- 'docs/**'
- 'mkdocs.yml'
- 'requirements.txt'
- 'package.json'
- '.github/workflows/build.yml'
workflow_dispatch:
inputs:
force:
description: 'Force rebuild (ignore auto flags)'
required: false
default: 'false'
schedule:
- cron: '0 */6 * * *'
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
pages: write
id-token: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Sync to latest branch tip
env:
BRANCH_NAME: ${{ github.ref_name }}
run: |
git fetch origin "$BRANCH_NAME"
git checkout "$BRANCH_NAME" || git switch -c "$BRANCH_NAME"
git reset --hard "origin/$BRANCH_NAME"
- name: Debounce to batch multiple merges
if: ${{ github.event_name == 'push' }}
env:
DEBOUNCE_SECONDS: ${{ vars.BUILD_DEBOUNCE_SECONDS }}
run: |
SLEEP=${DEBOUNCE_SECONDS:-30}
echo "Debouncing for ${SLEEP}s to batch merges..."
sleep "${SLEEP}"
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Install MkDocs and dependencies
run: |
pip install -r requirements.txt
- name: Install Node dependencies
run: |
npm ci
- name: Build (check changes)
id: check
run: |
npm run check || echo "CHANGED=$?" >> $GITHUB_OUTPUT
shell: bash
- name: Generate docs markdown from API
if: ${{ steps.check.outputs.CHANGED == '2' || github.event_name == 'workflow_dispatch' || github.event_name == 'push' }}
run: |
npm run docs-md-only
- name: Build MkDocs documentation
if: ${{ steps.check.outputs.CHANGED == '2' || github.event_name == 'workflow_dispatch' || github.event_name == 'push' }}
run: |
mkdocs build -d dist
- name: Build API data
if: ${{ steps.check.outputs.CHANGED == '2' || github.event_name == 'workflow_dispatch' || github.event_name == 'push' }}
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ inputs.force }}" = "true" ]; then
npm run api-only -- --force
else
npm run api-only
fi
- name: Commit and push changes
if: ${{ steps.check.outputs.CHANGED == '2' || github.event_name == 'workflow_dispatch' || github.event_name == 'push' }}
id: commit
env:
BRANCH_NAME: ${{ github.ref_name }}
run: |
if [ -n "$(git status --porcelain)" ]; then
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add dist
DT=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
if [ "${{ github.event_name }}" = "push" ]; then
TRIGGER_MSG="triggered by push to ${{ github.ref_name }}"
elif [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
if [ "${{ inputs.force }}" = "true" ]; then
TRIGGER_MSG="triggered by manual dispatch (force rebuild)"
else
TRIGGER_MSG="triggered by manual dispatch"
fi
elif [ "${{ github.event_name }}" = "schedule" ]; then
TRIGGER_MSG="triggered by scheduled run"
else
TRIGGER_MSG="triggered by ${{ github.event_name }}"
fi
COMMIT_MSG="📦 chore(dist): update static API - ${TRIGGER_MSG} [${DT}]"
git commit -m "${COMMIT_MSG}"
# Ensure we are rebased on the latest remote tip to avoid non-ff
git pull --rebase origin "$BRANCH_NAME" || true
# Push fast-forward
git push origin HEAD:"$BRANCH_NAME"
echo "COMMITTED=true" >> $GITHUB_OUTPUT
echo "COMMIT_MESSAGE=${COMMIT_MSG}" >> $GITHUB_OUTPUT
else
echo "No changes to commit"
echo "COMMITTED=false" >> $GITHUB_OUTPUT
fi
- name: Check for release trigger in commit message
if: ${{ github.event_name == 'push' }}
id: release_check
run: |
# Trigger release only if messages in THIS push contain 'release' (case-insensitive)
BEFORE_SHA="${{ github.event.before }}"
AFTER_SHA="${{ github.event.after }}"
echo "Scanning push range ${BEFORE_SHA}..${AFTER_SHA} for 'release'..."
RECENT_MSGS=$(git log --pretty=format:"%B" ${BEFORE_SHA}..${AFTER_SHA})
echo "$RECENT_MSGS" | sed -n '1,5p'
if echo "$RECENT_MSGS" | grep -i 'release' > /dev/null; then
echo "Release trigger found"
echo "SHOULD_RELEASE=true" >> $GITHUB_OUTPUT
else
echo "No release trigger found"
echo "SHOULD_RELEASE=false" >> $GITHUB_OUTPUT
fi
- name: Generate version and create release
if: ${{ github.event_name == 'push' && steps.release_check.outputs.SHOULD_RELEASE == 'true' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Generate timestamp-based version number
VERSION="v$(date -u +"%Y.%m.%d.%H%M")"
echo "Generated version: $VERSION"
# Tag the user commit (not the bot commit)
BEFORE_SHA="${{ github.event.before }}"
AFTER_SHA="${{ github.event.after }}"
git tag $VERSION ${AFTER_SHA}
git push origin $VERSION
# Build release notes from last version to this version, exclude github-actions[bot]
# Get the previous version tag
PREV_VERSION=$(git tag --sort=-version:refname | grep -E "^v[0-9]{4}\.[0-9]{2}\.[0-9]{2}\.[0-9]{4}$" | grep -v "^$VERSION$" | head -1)
if [ -n "$PREV_VERSION" ]; then
echo "Previous version found: $PREV_VERSION"
RECENT_COMMITS=$(git log --pretty=format:"%an%x09%s" ${PREV_VERSION}..${AFTER_SHA} | awk -F'\t' '$1!="github-actions[bot]" {print "- "$2}')
else
echo "No previous version found, using recent commits"
RECENT_COMMITS=$(git log --pretty=format:"%an%x09%s" --max-count=50 ${AFTER_SHA} | awk -F'\t' '$1!="github-actions[bot]" {print "- "$2}')
fi
# Fallback when no commits were found in the computed range
if [ -z "$RECENT_COMMITS" ]; then
RECENT_COMMITS="- No changes found"
fi
# Create release notes
cat > release_notes.md << EOF
## 🚀 Automated Release $VERSION
**Build Time:** $(date -u +"%Y-%m-%d %H:%M:%S UTC")
**Triggered By:** ${{ github.event_name }}
### 📋 Recent Changes
$RECENT_COMMITS
### 🔗 Usage
For complete API documentation and endpoints, visit: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}
> This version is automatically built and released via GitHub Actions
EOF
# Create release using GitHub CLI
gh release create $VERSION \
--title "$VERSION" \
--notes-file release_notes.md \
--latest
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: dist
deploy:
needs: build
runs-on: ubuntu-latest
concurrency:
group: pages
cancel-in-progress: true
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
permissions:
pages: write
id-token: write
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4