Repository navigation
FIX: Preserve word-selection parameters in converter identifiers #11804
Workflow file for this run
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: build-book | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - "releases/v*" | |
| paths: | |
| - ".github/workflows/docs.yml" | |
| - ".github/docs-versions.yml" | |
| - "build_scripts/**" | |
| - "doc/**" | |
| - "pyrit/**" | |
| - "assets/**" | |
| - "tests/unit/build_scripts/**" | |
| - "pyproject.toml" | |
| - "uv.lock" | |
| - ".python-version" | |
| - "README.md" | |
| - "LICENSE" | |
| - "MANIFEST.in" | |
| pull_request: | |
| branches: | |
| - main | |
| - "releases/**" | |
| paths: | |
| - ".github/workflows/docs.yml" | |
| - ".github/docs-versions.yml" | |
| - "build_scripts/**" | |
| - "doc/**" | |
| - "pyrit/**" | |
| - "assets/**" | |
| - "tests/unit/build_scripts/**" | |
| - "pyproject.toml" | |
| - "uv.lock" | |
| - ".python-version" | |
| - "README.md" | |
| - "LICENSE" | |
| - "MANIFEST.in" | |
| workflow_dispatch: | |
| # PRs, including forks, only need read access. Deployment grants are job-scoped. | |
| permissions: | |
| contents: read | |
| # Serialize the entire production pipeline, not just deployment, so a slow older | |
| # build cannot overwrite a newer site. PRs and release validation never join it. | |
| concurrency: | |
| group: >- | |
| ${{ github.event_name == 'pull_request' && format('docs-pr-{0}', github.event.pull_request.number) || | |
| github.ref == 'refs/heads/main' && 'pages' || format('docs-validation-{0}', github.ref) }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| env: | |
| # All versioned URLs live under /<repo-name>/<slug>/, e.g. /PyRIT/0.13.0/. | |
| DOCS_BASE: /${{ github.event.repository.name }} | |
| jobs: | |
| # ------------------------------------------------------------------ | |
| # 1. Read .github/docs-versions.yml and turn it into a build matrix. | |
| # ------------------------------------------------------------------ | |
| versions: | |
| name: Resolve version matrix | |
| runs-on: ubuntu-latest | |
| outputs: | |
| matrix: ${{ steps.matrix.outputs.matrix }} | |
| default: ${{ steps.matrix.outputs.default }} | |
| stable: ${{ steps.matrix.outputs.stable }} | |
| versions_json: ${{ steps.matrix.outputs.versions_json }} | |
| compose: ${{ steps.matrix.outputs.compose }} | |
| workflow_hash: ${{ steps.matrix.outputs.workflow_hash }} | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| ref: ${{ github.sha }} | |
| # The tested merge's first parent is the exact PR comparison base. | |
| fetch-depth: 2 | |
| sparse-checkout: | | |
| .github/docs-versions.yml | |
| .github/workflows/docs.yml | |
| /build_scripts/ | |
| sparse-checkout-cone-mode: false | |
| - name: Set up Python 3.13 | |
| uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 | |
| with: | |
| python-version: "3.13" | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0 | |
| with: | |
| version: "0.9.17" | |
| enable-cache: false | |
| - name: Compute matrix | |
| id: matrix | |
| env: | |
| # Hash the tested workflow before any release-branch checkout. | |
| WORKFLOW_HASH: ${{ hashFiles('.github/workflows/docs.yml') }} | |
| run: | | |
| uv run --no-project --with "pyyaml==6.0.3" python -m build_scripts.resolve_docs_matrix \ | |
| --config .github/docs-versions.yml \ | |
| --event-name "$GITHUB_EVENT_NAME" \ | |
| --ref "$GITHUB_REF" \ | |
| --sha "$GITHUB_SHA" \ | |
| --github-output "$GITHUB_OUTPUT" | |
| echo "workflow_hash=$WORKFLOW_HASH" >> "$GITHUB_OUTPUT" | |
| # ------------------------------------------------------------------ | |
| # 2. Build each version in parallel. | |
| # ------------------------------------------------------------------ | |
| build: | |
| name: Build ${{ matrix.slug }} | |
| needs: versions | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: ${{ fromJson(needs.versions.outputs.matrix) }} | |
| env: | |
| BASE_URL: ${{ format('/{0}/{1}', github.event.repository.name, matrix.slug) }} | |
| steps: | |
| - name: Checkout ${{ matrix.ref }} | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| ref: ${{ matrix.ref }} | |
| - name: Resolve commit SHA | |
| # PR previews use the immutable merge SHA. Other matrix refs may be | |
| # release branches, so always key the cache by the actual checkout. | |
| id: sha | |
| run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" | |
| - name: Restore built site from cache | |
| # Cache hit -> we skip the entire install + build pipeline and just | |
| # upload the restored doc/_build/html as the matrix artifact. Cache | |
| # miss -> we do a fresh build and actions/cache saves the result on | |
| # job success, so the next run with the same SHA hits. | |
| id: cache | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: doc/_build/html | |
| key: docs-${{ needs.versions.outputs.workflow_hash }}-${{ matrix.slug }}-${{ steps.sha.outputs.sha }} | |
| - name: Set up Python 3.13 | |
| if: steps.cache.outputs.cache-hit != 'true' | |
| uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 | |
| with: | |
| python-version: "3.13" | |
| - name: Install uv | |
| if: steps.cache.outputs.cache-hit != 'true' | |
| uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0 | |
| with: | |
| version: "0.9.17" | |
| enable-cache: true | |
| cache-dependency-glob: | | |
| **/pyproject.toml | |
| **/uv.lock | |
| - name: Install PyRIT with dev dependencies | |
| if: steps.cache.outputs.cache-hit != 'true' | |
| # Use `uv sync --frozen` so each release branch installs the exact | |
| # versions pinned in its own uv.lock. Frozen branch = frozen deps = | |
| # bit-for-bit reproducible rebuild forever. | |
| # | |
| # Newer release branches (incl. main) use PEP 735 [dependency-groups]; | |
| # older releases use legacy [project.optional-dependencies]. We pick | |
| # the right flag up front by reading pyproject.toml (via stdlib | |
| # tomllib) so any uv sync failure surfaces normally instead of being | |
| # swallowed by `|| fallback` with stderr redirected to /dev/null. | |
| run: | | |
| set -euo pipefail | |
| choice=$(python -c " | |
| import sys, tomllib | |
| d = tomllib.loads(open('pyproject.toml').read()) | |
| if 'dev' in (d.get('dependency-groups') or {}): | |
| print('--group dev') | |
| elif 'dev' in (d.get('project', {}).get('optional-dependencies') or {}): | |
| print('--extra dev') | |
| else: | |
| print('error: no dev group/extra in pyproject.toml', file=sys.stderr); sys.exit(1) | |
| ") | |
| echo "Installing with: uv sync --frozen $choice" | |
| uv sync --frozen $choice | |
| - name: Generate API reference (pydoc2json + gen_api_md) | |
| if: steps.cache.outputs.cache-hit != 'true' | |
| run: | | |
| uv run --frozen --no-sync python -m build_scripts.pydoc2json pyrit --submodules -o doc/_api/pyrit_all.json | |
| uv run --frozen --no-sync python -m build_scripts.gen_api_md | |
| - name: Build the static HTML site | |
| if: steps.cache.outputs.cache-hit != 'true' | |
| # --all builds frontmatter exports (PDF, per doc/myst.yml). | |
| # --html is required to produce the static HTML site we deploy. | |
| # NOT using --strict because older release branches have known | |
| # warnings (e.g. unresolved cross-refs) that aren't worth fixing | |
| # retroactively just to satisfy strict mode. | |
| working-directory: doc | |
| run: uv run --frozen --no-sync jupyter-book build --all --html | |
| - name: Upload built site | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: site-${{ matrix.slug }} | |
| path: doc/_build/html | |
| retention-days: 7 | |
| if-no-files-found: error | |
| # ------------------------------------------------------------------ | |
| # 3. Exercise composition on full matrices without deployment permissions. | |
| # ------------------------------------------------------------------ | |
| compose: | |
| name: Compose site | |
| needs: [versions, build] | |
| runs-on: ubuntu-latest | |
| if: needs.versions.outputs.compose == 'true' | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| ref: ${{ github.sha }} | |
| sparse-checkout: | | |
| .github/docs-versions.yml | |
| /build_scripts/ | |
| sparse-checkout-cone-mode: false | |
| - name: Set up Python 3.13 | |
| uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 | |
| with: | |
| python-version: "3.13" | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0 | |
| with: | |
| version: "0.9.17" | |
| enable-cache: false | |
| - name: Download all version artifacts | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| path: artifacts | |
| pattern: site-* | |
| - name: Compose dist/ | |
| # Compose script does everything: stage artifacts into dist/<slug>/, | |
| # write per-version pages.json manifests, write top-level versions.json, | |
| # write the root + /stable/ redirects, and write 404.html (with the | |
| # auto-redirect script that uses the manifest to find the closest | |
| # sibling page in the same version). | |
| run: | | |
| uv run --no-project --with "pyyaml==6.0.3" python -m build_scripts.compose_docs_dist \ | |
| --artifacts-dir artifacts \ | |
| --dist-dir dist \ | |
| --config .github/docs-versions.yml \ | |
| --base "${DOCS_BASE}" | |
| - name: Inject version picker | |
| run: | | |
| uv run --no-project python -m build_scripts.inject_version_picker \ | |
| --site-dir dist \ | |
| --base "${DOCS_BASE}" | |
| - name: Upload Pages artifact | |
| if: >- | |
| ${{ github.ref == 'refs/heads/main' && | |
| (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }} | |
| uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 | |
| with: | |
| path: dist | |
| # ------------------------------------------------------------------ | |
| # 4. Only main push/manual runs can publish the complete composed site. | |
| # ------------------------------------------------------------------ | |
| deploy: | |
| name: Deploy | |
| needs: compose | |
| runs-on: ubuntu-latest | |
| if: >- | |
| ${{ github.ref == 'refs/heads/main' && | |
| (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }} | |
| 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@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1 |