diff --git a/.github/workflows/deploy_docs.yml b/.github/workflows/deploy_docs.yml new file mode 100644 index 00000000..0424bd8e --- /dev/null +++ b/.github/workflows/deploy_docs.yml @@ -0,0 +1,187 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +# Workflow to build and deploy Sphinx documentation to GitHub Pages with versioning +name: Deploy Documentation to GitHub Pages +on: + push: + branches: [main] + tags: ['v*'] + pull_request: + branches: [main] + paths: + - 'bazel/rules/rules_score/docs/**' + - '.github/workflows/deploy_docs.yml' + workflow_dispatch: +permissions: + contents: write # needed for uploading release assets + pages: write + id-token: write +concurrency: + group: "pages" + cancel-in-progress: false +jobs: + build-docs: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6.0.2 + with: + fetch-depth: 0 # full history needed for tag-based version detection + - name: Setup Bazel with cache + uses: bazel-contrib/setup-bazel@0.19.0 + with: + disk-cache: true + repository-cache: true + bazelisk-cache: true + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y pkg-config libcairo2-dev + - name: Determine version + id: version + run: | + if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then + echo "version=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT" + echo "is_tag=true" >> "$GITHUB_OUTPUT" + elif [[ "${GITHUB_REF}" == refs/heads/main ]]; then + echo "version=latest" >> "$GITHUB_OUTPUT" + echo "is_tag=false" >> "$GITHUB_OUTPUT" + else + BRANCH_NAME="${GITHUB_REF#refs/heads/}" + echo "version=preview/${BRANCH_NAME//\//-}" >> "$GITHUB_OUTPUT" + echo "is_tag=false" >> "$GITHUB_OUTPUT" + fi + - name: Build Sphinx documentation + run: bazel build //bazel/rules/rules_score:rules_score_doc + - name: Prepare documentation output + run: | + BAZEL_BIN="$(bazel info bazel-bin)" + HTML_DIR="${BAZEL_BIN}/bazel/rules/rules_score/rules_score_doc/html" + + if [[ ! -d "${HTML_DIR}" ]]; then + echo "::error::Bazel HTML output not found at ${HTML_DIR}" + exit 1 + fi + + mkdir -p docs_output + cp -r "${HTML_DIR}/." docs_output/ + chmod -R u+w docs_output/ + + # Prevent Jekyll from ignoring _static directories + touch docs_output/.nojekyll + + # Inject version flyout CSS and JS into all HTML files + REPO_NAME="${{ github.event.repository.name }}" + find docs_output -name '*.html' -exec sed -i \ + -e "s||\n|" \ + -e "s|
+Redirecting to latest documentation...
+|\n|" \ + {} + + - name: Verify build output + run: | + if [[ ! -f docs_output/index.html ]]; then + echo "::error::Documentation build failed - no index.html found" + exit 1 + fi + echo "Documentation built successfully" + find docs_output -type f | wc -l | xargs -I{} echo "Total files: {}" + - name: Upload docs to release + if: startsWith(github.ref, 'refs/tags/v') + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + VERSION="${{ steps.version.outputs.version }}" + tar czf "docs-${VERSION}.tar.gz" -C docs_output . + gh release create "${VERSION}" --draft=false --notes "Release ${VERSION}" 2>/dev/null || true + gh release upload "${VERSION}" "docs-${VERSION}.tar.gz" --clobber + - name: Assemble publish tree + if: github.event_name != 'pull_request' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + VERSION="${{ steps.version.outputs.version }}" + IS_TAG="${{ steps.version.outputs.is_tag }}" + REPO_URL="https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}" + + # --- current build --- + mkdir -p "publish/${VERSION}" + cp -a docs_output/. "publish/${VERSION}/" + + # --- restore previously released versions --- + for tag in $(gh api "repos/${{ github.repository }}/releases" --paginate --jq '.[].tag_name' | grep '^v' || true); do + [[ "${tag}" == "${VERSION}" ]] && continue + if gh release download "${tag}" --pattern "docs-${tag}.tar.gz" --dir /tmp 2>/dev/null; then + mkdir -p "publish/${tag}" + tar xzf "/tmp/docs-${tag}.tar.gz" -C "publish/${tag}" + rm -f "/tmp/docs-${tag}.tar.gz" + echo "Restored ${tag} from release artifact" + else + echo "::warning::No docs artifact found for release ${tag}" + fi + done + + # --- set stable alias to newest tagged version --- + if [[ "${IS_TAG}" == "true" ]]; then + cp -a docs_output/. publish/stable/ + else + NEWEST_TAG="$(find publish -maxdepth 1 -mindepth 1 -type d -name 'v*' -printf '%f\n' | sort -rV | head -1)" + if [[ -n "${NEWEST_TAG}" ]]; then + cp -a "publish/${NEWEST_TAG}/." publish/stable/ + fi + fi + + # --- shared assets --- + mkdir -p publish/_shared/css publish/_shared/js + cp docs/_static/css/version_flyout.css publish/_shared/css/ + cp docs/_static/js/version_flyout.js publish/_shared/js/ + + # --- root index & Jekyll bypass --- + cp docs/_gh_pages/index.html publish/index.html + touch publish/.nojekyll + + # --- generate switcher.json --- + { + echo '[' + echo " {\"name\": \"latest\", \"version\": \"latest\", \"url\": \"${REPO_URL}/latest/\"}" + + if [[ -d publish/stable ]]; then + echo " ,{\"name\": \"stable\", \"version\": \"stable\", \"url\": \"${REPO_URL}/stable/\", \"preferred\": true}" + fi + + for dir in $(find publish -maxdepth 1 -mindepth 1 -type d -name 'v*' | sort -rV); do + ver="$(basename "${dir}")" + echo " ,{\"name\": \"${ver}\", \"version\": \"${ver}\", \"url\": \"${REPO_URL}/${ver}/\"}" + done + + echo ']' + } > publish/switcher.json + - name: Upload Pages artifact + if: github.event_name != 'pull_request' + uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 + with: + path: publish + - name: Print preview URL + if: github.event_name != 'pull_request' + run: | + echo "::notice::Documentation deployed to: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/${{ steps.version.outputs.version }}/" + deploy-pages: + needs: build-docs + if: github.event_name != 'pull_request' + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 diff --git a/bazel/rules/rules_score/templates/conf.template.py b/bazel/rules/rules_score/templates/conf.template.py index 454254ed..7730c694 100644 --- a/bazel/rules/rules_score/templates/conf.template.py +++ b/bazel/rules/rules_score/templates/conf.template.py @@ -153,4 +153,8 @@ # HTML theme html_theme = "sphinx_rtd_theme" + +# Note: version_flyout.css and version_flyout.js are injected by the +# deploy workflow via _shared/ paths so they load once across all versions. + logger.debug("#" * 80) diff --git a/docs/_gh_pages/index.html b/docs/_gh_pages/index.html new file mode 100644 index 00000000..f25bd0fe --- /dev/null +++ b/docs/_gh_pages/index.html @@ -0,0 +1,26 @@ + + + +
+ +
+ + + +
+