Skip to content

Commit 80cf445

Browse files
Merge branch 'main' into feature/stats
2 parents 72df096 + bb40ec7 commit 80cf445

33 files changed

Lines changed: 675 additions & 168 deletions
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
name: Generate docs
2+
permissions:
3+
contents: read
4+
5+
# Generates Doxygen docs and uploads them as a workflow artifact.
6+
7+
# This workflow is used to validate documentation before merge, for example catching
8+
# things like broken @ref tags, missing @param tags, etc.
9+
10+
# The artifact is attached to the workflow run so reviewers can download a preview,
11+
# but also to verify the documentation artifact is valid for subsequent release runs
12+
# that will publish them to the LiveKit docs web page: https://docs.livekit.io/reference/client-sdk-cpp/
13+
on:
14+
pull_request:
15+
branches: ["main"]
16+
paths:
17+
- include/**
18+
- src/**
19+
- docs/**
20+
- scripts/generate-docs.sh
21+
- .github/workflows/generate-docs.yml
22+
- .github/workflows/publish-docs.yml
23+
workflow_call:
24+
inputs:
25+
version:
26+
description: 'Documentation version (e.g. v0.1.0)'
27+
required: false
28+
type: string
29+
upload_artifact:
30+
description: 'Upload the generated docs folder as a workflow artifact'
31+
required: false
32+
type: boolean
33+
default: true
34+
artifact_name:
35+
description: 'Name to use for the uploaded docs artifact'
36+
required: false
37+
type: string
38+
default: livekit-cpp-docs
39+
artifact_retention_days:
40+
description: 'Retention (days) for the uploaded docs artifact'
41+
required: false
42+
type: number
43+
default: 7
44+
outputs:
45+
project_number:
46+
description: 'Doxygen PROJECT_NUMBER used for the build (e.g., v1.2.3)'
47+
value: ${{ jobs.validate.outputs.project_number }}
48+
artifact_name:
49+
description: 'Name of the uploaded docs artifact (empty if upload was skipped via upload_artifact: false)'
50+
value: ${{ jobs.validate.outputs.artifact_name }}
51+
52+
jobs:
53+
validate:
54+
name: Generate and verify docs
55+
runs-on: ubuntu-latest
56+
outputs:
57+
project_number: ${{ steps.build_docs.outputs.project_number }}
58+
artifact_name: ${{ steps.artifact_meta.outputs.name }}
59+
steps:
60+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
61+
with:
62+
# fetch-depth: 0 is required so `git describe --tags` in
63+
# scripts/generate-docs.sh resolves the right version from the git history.
64+
fetch-depth: 0
65+
66+
# Doxygen is available on ubuntu-latest, but we install explicitly for stability
67+
- name: Install Doxygen
68+
run: |
69+
sudo apt-get update
70+
sudo apt-get install -y doxygen graphviz
71+
72+
- name: Generate docs (Doxygen)
73+
id: build_docs
74+
shell: bash
75+
env:
76+
INPUT_VERSION: ${{ inputs.version || '' }}
77+
run: |
78+
set -euo pipefail
79+
80+
args=()
81+
if [[ -n "$INPUT_VERSION" ]]; then
82+
args+=(--version "$INPUT_VERSION")
83+
elif [[ "${{ github.ref_type }}" == "tag" ]]; then
84+
args+=(--version "${{ github.ref_name }}")
85+
fi
86+
87+
./scripts/generate-docs.sh "${args[@]}"
88+
89+
- name: Print docs version
90+
shell: bash
91+
run: |
92+
set -euo pipefail
93+
94+
PROJECT_NUMBER="${{ steps.build_docs.outputs.project_number }}"
95+
96+
if [[ -z "$PROJECT_NUMBER" ]]; then
97+
echo "ERROR: build_docs step did not emit a project_number output."
98+
exit 1
99+
fi
100+
101+
echo "Docs version: ${PROJECT_NUMBER}"
102+
103+
{
104+
echo "Docs version: \`${PROJECT_NUMBER}\`"
105+
echo ""
106+
echo "> Note: On a non-tag/release run, the version will resolve to:"
107+
echo " \`<closest tag>-<commits since tag>-<commit sha>\`"
108+
} >>"$GITHUB_STEP_SUMMARY"
109+
110+
- name: Verify docs were generated
111+
shell: bash
112+
run: |
113+
set -euo pipefail
114+
if [[ ! -f docs/doxygen/html/index.html ]]; then
115+
echo "ERROR: Expected docs at docs/doxygen/html/index.html but file not found."
116+
exit 1
117+
fi
118+
119+
# `inputs.*` is only populated on `workflow_call`. On a direct
120+
# `pull_request` trigger every `inputs.*` lookup is the empty string, so
121+
# we OR-fold to the documented defaults to keep PR runs behaving the same
122+
# as the workflow_call default of `upload_artifact: true`.
123+
- name: Resolve artifact metadata
124+
id: artifact_meta
125+
if: inputs.upload_artifact || github.event_name == 'pull_request'
126+
shell: bash
127+
env:
128+
INPUT_NAME: ${{ inputs.artifact_name || 'livekit-cpp-docs' }}
129+
INPUT_RETENTION: ${{ inputs.artifact_retention_days || '7' }}
130+
run: |
131+
set -euo pipefail
132+
if [[ -z "$INPUT_NAME" ]]; then
133+
echo "ERROR: artifact name resolved to empty."
134+
exit 1
135+
fi
136+
echo "name=${INPUT_NAME}" >>"$GITHUB_OUTPUT"
137+
echo "retention=${INPUT_RETENTION}" >>"$GITHUB_OUTPUT"
138+
139+
- name: Upload docs artifact
140+
if: steps.artifact_meta.outputs.name != ''
141+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
142+
with:
143+
name: ${{ steps.artifact_meta.outputs.name }}
144+
path: docs/doxygen/html/
145+
retention-days: ${{ steps.artifact_meta.outputs.retention }}
146+
if-no-files-found: error
147+
148+
# Simple check to make sure the documentation artifact is valid.
149+
- name: Re-download artifact (publish workflow pre-validation)
150+
if: steps.artifact_meta.outputs.name != ''
151+
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
152+
with:
153+
name: ${{ steps.artifact_meta.outputs.name }}
154+
path: html
155+
156+
- name: Inspect downloaded artifact
157+
if: steps.artifact_meta.outputs.name != ''
158+
shell: bash
159+
run: |
160+
set -euo pipefail
161+
162+
NAME="${{ steps.artifact_meta.outputs.name }}"
163+
ROOT="html"
164+
165+
echo "Artifact '${NAME}' extracted into '${ROOT}/'. Top-level contents:"
166+
# `sed -n '1,Np'` reads the whole pipe before truncating its output,
167+
# so the producer (ls) never hits SIGPIPE under `pipefail`.
168+
ls -la "$ROOT" | sed -n '1,40p'
169+
170+
TOTAL=$(find "$ROOT" -type f | wc -l | tr -d ' ')
171+
echo "Total files: ${TOTAL}"
172+
173+
if [[ ! -f "${ROOT}/index.html" ]]; then
174+
echo "ERROR: ${ROOT}/index.html is missing -- artifact layout regressed."
175+
echo " publish-docs.yml expects html/index.html."
176+
exit 1
177+
fi

.github/workflows/make-release.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,8 @@ jobs:
341341
permissions:
342342
contents: write
343343
if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch'
344+
outputs:
345+
version: ${{ steps.version.outputs.version }}
344346

345347
steps:
346348
- name: Checkout
@@ -434,4 +436,6 @@ jobs:
434436
name: Publish Documentation
435437
needs: release
436438
uses: ./.github/workflows/publish-docs.yml
439+
with:
440+
version: ${{ needs.release.outputs.version }}
437441
secrets: inherit

.github/workflows/publish-docs.yml

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,43 @@ name: Publish docs
22

33
on:
44
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: 'Documentation version (e.g. v0.1.0)'
8+
required: false
9+
type: string
510
workflow_call:
11+
inputs:
12+
version:
13+
description: 'Documentation version (e.g. v0.1.0)'
14+
required: false
15+
type: string
16+
17+
permissions:
18+
contents: read
19+
actions: read
620

721
jobs:
8-
docs:
22+
validate:
23+
name: Validate (build docs)
24+
uses: ./.github/workflows/generate-docs.yml
25+
with:
26+
version: ${{ inputs.version || github.event.inputs.version || '' }}
27+
upload_artifact: true
28+
# Suffix with run_id so concurrent publish runs cannot collide on the
29+
# artifact namespace within the same repository.
30+
artifact_name: livekit-cpp-docs-${{ github.run_id }}
31+
32+
publish:
33+
name: Publish (S3 + CloudFront)
34+
needs: validate
935
runs-on: ubuntu-latest
1036
steps:
11-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
12-
# Note: submodules and LFS not needed for docs generation
13-
# Doxygen only reads from include/, docs/, README.md, and examples/
14-
15-
# Doxygen is available on ubuntu-latest, but we install explicitly for stability
16-
- name: Install Doxygen
17-
run: |
18-
sudo apt-get update
19-
sudo apt-get install -y doxygen graphviz
20-
21-
- name: Build Docs (Doxygen)
22-
run: |
23-
doxygen docs/Doxyfile
37+
- name: Download docs artifact
38+
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
39+
with:
40+
name: ${{ needs.validate.outputs.artifact_name }}
41+
path: html
2442

2543
- name: S3 Upload
2644
run: |
@@ -30,8 +48,12 @@ jobs:
3048
exit 1
3149
fi
3250
33-
# Upload to rolling latest (no versioned docs, always overwrite)
34-
aws s3 cp "$DOCS_DIR"/ s3://livekit-docs/client-sdk-cpp --recursive
51+
VERSIONED_PREFIX="s3://livekit-docs/client-sdk-cpp/${{ needs.validate.outputs.project_number }}"
52+
LATEST_PREFIX="s3://livekit-docs/client-sdk-cpp"
53+
54+
# Upload immutable versioned docs, then refresh rolling latest.
55+
aws s3 cp "$DOCS_DIR"/ "$VERSIONED_PREFIX" --recursive
56+
aws s3 cp "$DOCS_DIR"/ "$LATEST_PREFIX" --recursive
3557
env:
3658
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
3759
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

.gitignore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ vcpkg_installed/
1616
include/livekit/build.h
1717
received_green.avif
1818
docs/*.bak
19-
docs/html/
20-
docs/latex/
19+
# Doxygen
20+
docs/doxygen/html/
21+
docs/doxygen/latex/
2122
.vs/
2223
.vscode/
2324
.cursor/

AGENTS.md

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ Be sure to update the directory layout in this file if the directory layout chan
8080
| `cmake/` | Build helpers (`protobuf.cmake`, `spdlog.cmake`, `LiveKitConfig.cmake.in`) |
8181
| `docker/` | Dockerfile for CI and SDK distribution images |
8282
| `scripts/` | Developer / CI helper scripts (e.g. `clang-tidy.sh`) |
83+
| `docs/` | Documentation root. `docs/` holds hand-written long-form Markdown intended to also read well on GitHub. |
84+
| `docs/doxygen/` | Doxygen tool config, theme assets, and Doxygen-only content (`Doxyfile`, `index.md` mainpage, `customization/*.css`, `customization/header.html`, `customization/favicon.ico`). Files here use Doxygen-only syntax (`@ref`, `@brief`, …) and are not intended for human reading on their own. |
8385
| `.github/workflows/` | GitHub Actions CI workflows |
8486

8587
### Key Types
@@ -238,7 +240,7 @@ with the same library loaded elsewhere in the host process.
238240
### Public API Documentation (Doxygen)
239241

240242
The public API (`include/livekit/*.h`) is what consumers read first and is also
241-
published as a Doxygen site (`docs/Doxyfile`, `.github/workflows/publish-docs.yml`).
243+
published as a Doxygen site (`docs/doxygen/Doxyfile`, `.github/workflows/publish-docs.yml`).
242244
Every doc comment in `include/livekit/` must use the rules below, and PRs that
243245
add or modify public symbols are gated on these rules during review.
244246

@@ -259,12 +261,13 @@ add or modify public symbols are gated on these rules during review.
259261

260262
#### Required tags
261263

264+
- Document class/structs succinctly using `@brief Description.`
265+
- Document functions/methods/namespaces succinctly using `@brief Description.`
262266
- Document parameters using `@param name Description.`
263267
- Document non-void return values using `@return Description.`
264-
- Document thrown exceptions using `@throws ExceptionType When/why it's
265-
thrown.` Operations that can fail without throwing should return
266-
`Result<T, E>` (see Error Handling above) and the variants should be
267-
documented in the doc block.
268+
- Document thrown exceptions using `@throws ExceptionType When/why it's thrown.`
269+
Operations that can fail without throwing should return `Result<T, E>`
270+
(see Error Handling above) and the variants should be documented in the doc block.
268271
- Free-text "Parameters:", "Returns:", "Throws:" sections in legacy comments
269272
must be converted to the corresponding `@param` / `@return` / `@throws`
270273
tags when the comment is touched.
@@ -290,15 +293,17 @@ render a deprecation callout (see "Deprecating a public API" above).
290293
291294
#### Verifying locally
292295
293-
Run Doxygen from the repository root to regenerate the HTML docs:
296+
Run the docs build script from the repository root:
294297
295298
```bash
296-
doxygen docs/Doxyfile
299+
./scripts/generate-docs.sh
297300
```
298301

299-
The output lands in `docs/html/`. Doxygen warnings about "is not documented"
300-
indicate undocumented public symbols — adding documentation to them is
301-
encouraged but not strictly required by these rules.
302+
The output lands in `docs/doxygen/html/index.html`. The Doxyfile sets
303+
`WARN_IF_UNDOCUMENTED = NO` (the 400+ "X is not documented" warnings for
304+
internal symbols are too noisy to enforce) and `WARN_AS_ERROR = FAIL_ON_WARNINGS`,
305+
so any other warning (broken `@ref`, unknown `@command`, unsupported HTML tag,
306+
malformed table, missing `@param` on a documented function, …) fails the build.
302307

303308
### Integer Types
304309

0 commit comments

Comments
 (0)