Doxygen second pass: coverage, improvements, fixes, etc. #10
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: Generate docs | |
| permissions: | |
| contents: read | |
| # Builds the Doxygen docs and uploads them as a workflow artifact (without | |
| # publishing). Two roles: | |
| # | |
| # 1. Dry-run on every PR that touches C++ code (or other Doxygen inputs) so | |
| # docs breakage is caught before merge. The artifact is attached to the | |
| # workflow run so reviewers can download a preview. | |
| # 2. Reusable workflow consumed by publish-docs.yml: builds the docs, prints | |
| # the resolved version, and uploads the docs/doxygen/html/ directory as an | |
| # artifact for a downstream publish job to consume. Avoids double-building | |
| # the docs. | |
| # | |
| # Artifact layout: actions/upload-artifact@v4+ uses the longest common path of | |
| # all uploaded files as the artifact root. With `path: docs/doxygen/html/`, the | |
| # artifact contains the *contents* of that directory at the artifact root | |
| # (index.html, favicon.ico, …) -- NOT nested under docs/doxygen/html/. The | |
| # `html/` prefix that publish-docs.yml relies on comes from the *download* | |
| # step's `path: html` parameter, not from the artifact itself. The | |
| # "Re-download artifact" + "Inspect downloaded artifact" steps below prove | |
| # this end-to-end on every run by re-downloading with `path: html` and | |
| # asserting `html/index.html` is present. | |
| on: | |
| pull_request: | |
| branches: ["main"] | |
| paths: | |
| - include/** | |
| - src/** | |
| - examples/** | |
| - docs/** | |
| - README.md | |
| - scripts/generate-docs.sh | |
| - .github/workflows/generate-docs.yml | |
| - .github/workflows/publish-docs.yml | |
| workflow_call: | |
| inputs: | |
| version: | |
| description: 'Documentation version (e.g. v0.1.0)' | |
| required: false | |
| type: string | |
| upload_artifact: | |
| description: 'Upload the built docs/doxygen/html/ tree as a workflow artifact' | |
| required: false | |
| type: boolean | |
| default: true | |
| artifact_name: | |
| description: 'Name to use for the uploaded docs artifact' | |
| required: false | |
| type: string | |
| default: livekit-cpp-docs | |
| artifact_retention_days: | |
| description: 'Retention (days) for the uploaded docs artifact. Default tuned for PR-preview use.' | |
| required: false | |
| type: number | |
| default: 7 | |
| outputs: | |
| project_number: | |
| description: 'Doxygen PROJECT_NUMBER used for the build (e.g., v1.2.3)' | |
| value: ${{ jobs.validate.outputs.project_number }} | |
| artifact_name: | |
| description: 'Name of the uploaded docs artifact (empty if upload was skipped via upload_artifact: false)' | |
| value: ${{ jobs.validate.outputs.artifact_name }} | |
| jobs: | |
| validate: | |
| name: Generate and verify docs | |
| runs-on: ubuntu-latest | |
| outputs: | |
| project_number: ${{ steps.build_docs.outputs.project_number }} | |
| artifact_name: ${{ steps.artifact_meta.outputs.name }} | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| # fetch-depth: 0 is required so `git describe --tags` in | |
| # scripts/generate-docs.sh resolves the right version from the git history. | |
| fetch-depth: 0 | |
| # Doxygen is available on ubuntu-latest, but we install explicitly for stability | |
| - name: Install Doxygen | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y doxygen graphviz | |
| - name: Generate docs (Doxygen) | |
| id: build_docs | |
| shell: bash | |
| env: | |
| INPUT_VERSION: ${{ inputs.version || '' }} | |
| run: | | |
| set -euo pipefail | |
| args=() | |
| if [[ -n "$INPUT_VERSION" ]]; then | |
| args+=(--version "$INPUT_VERSION") | |
| elif [[ "${{ github.ref_type }}" == "tag" ]]; then | |
| args+=(--version "${{ github.ref_name }}") | |
| fi | |
| ./scripts/generate-docs.sh "${args[@]}" | |
| - name: Print docs version | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| PROJECT_NUMBER="${{ steps.build_docs.outputs.project_number }}" | |
| if [[ -z "$PROJECT_NUMBER" ]]; then | |
| echo "ERROR: build_docs step did not emit a project_number output." | |
| exit 1 | |
| fi | |
| echo "Docs version: ${PROJECT_NUMBER}" | |
| { | |
| echo "Version: \`${PROJECT_NUMBER}\`" | |
| echo "" | |
| echo "> Note: On a non-tag/release run, the version will resolve to:" | |
| echo " \`<closest tag>-<commits since tag>-<commit sha>\`" | |
| } >>"$GITHUB_STEP_SUMMARY" | |
| - name: Verify docs were generated | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if [[ ! -f docs/doxygen/html/index.html ]]; then | |
| echo "ERROR: Expected docs at docs/doxygen/html/index.html but file not found." | |
| exit 1 | |
| fi | |
| # `inputs.*` is only populated on `workflow_call`. On a direct | |
| # `pull_request` trigger every `inputs.*` lookup is the empty string, so | |
| # we OR-fold to the documented defaults to keep PR runs behaving the same | |
| # as the workflow_call default of `upload_artifact: true`. | |
| - name: Resolve artifact metadata | |
| id: artifact_meta | |
| if: inputs.upload_artifact || github.event_name == 'pull_request' | |
| shell: bash | |
| env: | |
| INPUT_NAME: ${{ inputs.artifact_name || 'livekit-cpp-docs' }} | |
| INPUT_RETENTION: ${{ inputs.artifact_retention_days || '7' }} | |
| run: | | |
| set -euo pipefail | |
| if [[ -z "$INPUT_NAME" ]]; then | |
| echo "ERROR: artifact name resolved to empty." | |
| exit 1 | |
| fi | |
| echo "name=${INPUT_NAME}" >>"$GITHUB_OUTPUT" | |
| echo "retention=${INPUT_RETENTION}" >>"$GITHUB_OUTPUT" | |
| - name: Upload docs artifact | |
| if: steps.artifact_meta.outputs.name != '' | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: ${{ steps.artifact_meta.outputs.name }} | |
| path: docs/doxygen/html/ | |
| retention-days: ${{ steps.artifact_meta.outputs.retention }} | |
| if-no-files-found: error | |
| # Empirical proof of the publish-docs.yml contract: re-download the | |
| # just-uploaded artifact using the *same* `path: html` value that | |
| # publish-docs.yml uses, and assert html/index.html exists. The artifact | |
| # itself is flat (its root contains index.html, favicon.ico, …); the | |
| # `html/` prefix comes purely from the download step's `path:`. If | |
| # actions/upload-artifact ever changes its "longest common path" root | |
| # behavior, this assertion fails loudly. | |
| - name: Re-download artifact (mirrors publish-docs.yml exactly) | |
| if: steps.artifact_meta.outputs.name != '' | |
| uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 | |
| with: | |
| name: ${{ steps.artifact_meta.outputs.name }} | |
| path: html | |
| - name: Inspect downloaded artifact | |
| if: steps.artifact_meta.outputs.name != '' | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| NAME="${{ steps.artifact_meta.outputs.name }}" | |
| ROOT="html" | |
| echo "Artifact '${NAME}' extracted into '${ROOT}/'. Top-level contents:" | |
| # `sed -n '1,Np'` reads the whole pipe before truncating its output, | |
| # so the producer (ls) never hits SIGPIPE under `pipefail`. | |
| ls -la "$ROOT" | sed -n '1,40p' | |
| TOTAL=$(find "$ROOT" -type f | wc -l | tr -d ' ') | |
| echo "Total files: ${TOTAL}" | |
| if [[ ! -f "${ROOT}/index.html" ]]; then | |
| echo "ERROR: ${ROOT}/index.html is missing -- artifact layout regressed." | |
| echo " publish-docs.yml downloads with the same 'path: html' and" | |
| echo " expects html/index.html." | |
| exit 1 | |
| fi | |
| SAMPLE=$( (cd "$ROOT" && ls -1) | sed -n '1,20p' ) | |
| { | |
| echo "### Docs artifact: \`${NAME}\`" | |
| echo "" | |
| echo "Uploaded ${TOTAL} files. The artifact's *contents* live at" | |
| echo "the artifact root (there is no \`html/\` prefix inside the" | |
| echo "artifact itself). The \`html/\` directory below comes from" | |
| echo "this step's \`path: html\`, which mirrors \`publish-docs.yml\`:" | |
| echo "" | |
| echo '```' | |
| echo "${SAMPLE}" | |
| echo '```' | |
| echo "" | |
| echo "Layout confirmed: \`html/index.html\` is present, so the" | |
| echo "\`aws s3 cp html/ s3://… --recursive\` step in" | |
| echo "\`publish-docs.yml\` will publish \`index.html\`, \`favicon.ico\`," | |
| echo "etc. at the bucket root." | |
| } >>"$GITHUB_STEP_SUMMARY" |