Skip to content

Build documentation DB #7

Build documentation DB

Build documentation DB #7

Workflow file for this run

name: Build documentation DB
# Manual trigger only. A rebuild costs real money (a full run compresses ~1230
# documents, roughly 3.5M output tokens), so it is always a deliberate decision.
on:
workflow_dispatch:
inputs:
mode:
description: Recompress everything, or only what changed upstream
type: choice
options: [incremental, full]
default: incremental
frameworks:
description: Comma-separated subset to rebuild
type: string
default: angular,react,blazor,webcomponents
submodule_branch:
description: Branch to move the documentation submodules to
type: string
default: master
model:
description: Compression model override (empty uses the script default)
type: string
default: ""
permissions:
contents: read
jobs:
# The four compress jobs run strictly one after another. Their state is per-framework
# so they *could* run in parallel, but concurrent batch submissions contend for the
# same account-level OpenAI limits — in particular enqueued tokens per model.
angular:
if: contains(inputs.frameworks, 'angular')
runs-on: ubuntu-latest
timeout-minutes: 330
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/build-framework-docs
with:
framework: angular
mode: ${{ inputs.mode }}
model: ${{ inputs.model }}
submodule-branch: ${{ inputs.submodule_branch }}
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
react:
needs: angular
if: always() && !cancelled() && !contains(needs.*.result, 'failure') && contains(inputs.frameworks, 'react')
runs-on: ubuntu-latest
timeout-minutes: 330
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/build-framework-docs
with:
framework: react
mode: ${{ inputs.mode }}
model: ${{ inputs.model }}
submodule-branch: ${{ inputs.submodule_branch }}
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
blazor:
needs: react
if: always() && !cancelled() && !contains(needs.*.result, 'failure') && contains(inputs.frameworks, 'blazor')
runs-on: ubuntu-latest
timeout-minutes: 330
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/build-framework-docs
with:
framework: blazor
mode: ${{ inputs.mode }}
model: ${{ inputs.model }}
submodule-branch: ${{ inputs.submodule_branch }}
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
webcomponents:
needs: blazor
if: always() && !cancelled() && !contains(needs.*.result, 'failure') && contains(inputs.frameworks, 'webcomponents')
runs-on: ubuntu-latest
timeout-minutes: 330
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/build-framework-docs
with:
framework: webcomponents
mode: ${{ inputs.mode }}
model: ${{ inputs.model }}
submodule-branch: ${{ inputs.submodule_branch }}
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
# The database is assembled exactly once, here, with every framework's docs present.
# A per-framework build:db on a fresh runner finds no existing DB and rebuilds from
# scratch with only that framework — the bug that shipped a 112-doc and later an
# angular-only database.
assemble:
needs: [angular, react, blazor, webcomponents]
if: always() && !cancelled() && !contains(needs.*.result, 'failure')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24.x
cache: yarn
- name: Install packages
run: yarn --frozen-lockfile
- uses: actions/download-artifact@v8
with:
pattern: docs-final-*
path: packages/igniteui-mcp/igniteui-doc-mcp/dist/docs_final
- uses: actions/download-artifact@v8
with:
pattern: docs-prepeared-*
path: packages/igniteui-mcp/igniteui-doc-mcp/dist/docs_prepeared
- uses: actions/download-artifact@v8
with:
pattern: docs-baseline-*
path: packages/igniteui-mcp/igniteui-doc-mcp/docs_baseline
# download-artifact nests each artifact under its own name; flatten to the
# framework directories that build-db expects.
- name: Flatten artifact layout
working-directory: packages/igniteui-mcp/igniteui-doc-mcp
run: |
set -euo pipefail
for kind in docs_final:dist/docs_final docs_prepeared:dist/docs_prepeared docs_baseline:docs_baseline; do
prefix="${kind%%:*}"; dir="${kind##*:}"
for fw in angular react blazor webcomponents; do
src="$dir/${prefix//_/-}-$fw"
[ -d "$src" ] && rm -rf "$dir/$fw" && mv "$src" "$dir/$fw" || true
done
done
ls -la dist/docs_final
# Any framework missing from this run keeps the copy already committed, so the
# database is always assembled from a complete set. --toc-stubs also emits the
# minimal docs_prepeared entries build-db needs to populate toc_name.
- name: Restore frameworks not rebuilt in this run
working-directory: packages/igniteui-mcp/igniteui-doc-mcp
env:
REQUESTED: ${{ inputs.frameworks }}
run: |
set -euo pipefail
for fw in angular react blazor webcomponents; do
if [ -d "dist/docs_final/$fw" ] && [ -n "$(ls -A "dist/docs_final/$fw" 2>/dev/null)" ]; then
continue
fi
# A framework that was rebuilt but has no docs here means its artifact did
# not arrive. Restoring from the DB would silently publish stale docs for it
# with counts that look perfectly healthy, so fail instead.
if echo "$REQUESTED" | grep -qw "$fw"; then
echo "::error::$fw was part of this run but its artifact is missing — refusing to build a database from stale $fw documents."
ls -R dist/docs_final || true
exit 1
fi
echo "$fw was not part of this run — restoring from the committed DB"
npx tsx scripts/restore-docs-final.ts --framework "$fw" --toc-stubs
done
- name: Build database
working-directory: packages/igniteui-mcp/igniteui-doc-mcp
run: npm run build:db
- name: Verify document counts
run: |
npx tsc spec/unit/docs-db-counts-spec.ts --target es6 --module commonjs --esModuleInterop --skipLibCheck
npx jasmine spec/unit/docs-db-counts-spec.js
- uses: actions/upload-artifact@v7
with:
name: igniteui-docs-db
path: |
packages/igniteui-mcp/igniteui-doc-mcp/db/igniteui-docs.db
packages/igniteui-mcp/igniteui-doc-mcp/docs_baseline
retention-days: 5
# The only job that writes to the repository. It opens a PR for review — nothing is
# pushed to a protected branch and nothing auto-merges.
publish:
needs: assemble
# Not `success()`: at job level that evaluates the whole ancestor chain, so a run
# scoped to a subset of frameworks (leaving the others skipped) would make it false
# and silently skip publishing. Check the direct dependency's result instead.
if: always() && !cancelled() && needs.assemble.result == 'success'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v6
- uses: actions/download-artifact@v8
with:
name: igniteui-docs-db
path: artifact
- name: Apply rebuilt database and baselines
run: |
set -euo pipefail
# upload-artifact roots an artifact at the least common ancestor of its paths,
# so the layout under artifact/ depends on which paths were uploaded together.
# Locate the contents instead of assuming a depth — this step runs after hours
# of compression, so it must not fail on a path guess.
DB=$(find artifact -type f -name igniteui-docs.db | head -1)
BASELINE=$(find artifact -type d -name docs_baseline | head -1)
if [ -z "$DB" ] || [ -z "$BASELINE" ]; then
echo "::error::Could not locate the database or baselines in the artifact."
find artifact
exit 1
fi
echo "Using DB: $DB"
echo "Using baselines: $BASELINE"
cp "$DB" packages/igniteui-mcp/igniteui-doc-mcp/db/igniteui-docs.db
# Kept in sync with the doc-mcp copy, as every prior doc-update commit has done.
cp "$DB" packages/igniteui-mcp/docs-backend/docs-backend/igniteui-docs.db
rm -rf packages/igniteui-mcp/igniteui-doc-mcp/docs_baseline
cp -r "$BASELINE" packages/igniteui-mcp/igniteui-doc-mcp/docs_baseline
rm -rf artifact
- name: Commit and open pull request
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
BRANCH="chore/docs-db-${{ github.run_id }}"
git config user.name github-actions
git config user.email github-actions@github.com
git checkout -b "$BRANCH"
# Submodule pointers are deliberately excluded — the release pipeline checks
# submodules out fresh, so recording them here would only add noise.
git add packages/igniteui-mcp/igniteui-doc-mcp/db/igniteui-docs.db \
packages/igniteui-mcp/docs-backend/docs-backend/igniteui-docs.db \
packages/igniteui-mcp/igniteui-doc-mcp/docs_baseline
if git diff --cached --quiet; then
echo "No changes to publish — the documentation is already up to date."
exit 0
fi
git commit -m "chore(mcp): rebuild documentation database (${{ inputs.mode }})"
git push origin "$BRANCH"
gh pr create \
--base "${{ github.ref_name }}" \
--head "$BRANCH" \
--title "chore(mcp): rebuild documentation database" \
--body "Automated rebuild of the Ignite UI documentation database.
| | |
|---|---|
| mode | \`${{ inputs.mode }}\` |
| frameworks | \`${{ inputs.frameworks }}\` |
| submodule branch | \`${{ inputs.submodule_branch }}\` |
| model | \`${{ inputs.model || 'script default' }}\` |
| run | [#${{ github.run_id }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) |
Document counts were verified by \`spec/unit/docs-db-counts-spec.ts\` before this PR was opened.
Requires manual review and merge."