Skip to content

Commit 5b07189

Browse files
committed
Docs: provide option to skip analysis in doc-check
Some projects may not want to run the `--analyze` option on the DocC generation until they are ready. Provide an workflow input option to skip the analyze. While at it, update the `check-docs.sh` script to accept arugments instead of relying on environment variables being set. This allows more easily run the script at-desk. Fixes #2181
1 parent c8aaa3d commit 5b07189

8 files changed

Lines changed: 222 additions & 7 deletions

File tree

.github/workflows/pull_request.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,5 @@ jobs:
9595
uses: ./.github/workflows/soundness.yml
9696
with:
9797
api_breakage_check_enabled: false
98+
docs_check_enabled: false
9899
license_header_check_project_name: "Swift.org"

.github/workflows/scripts/check-docs.sh

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,61 @@ log() { printf -- "** %s\n" "$*" >&2; }
1717
error() { printf -- "** ERROR: %s\n" "$*" >&2; }
1818
fatal() { error "$@"; exit 1; }
1919

20+
usage() {
21+
cat <<EOF
22+
Usage: $(basename "$0") [options]
23+
24+
Options:
25+
--no-analyze Do not pass --analyze to 'swift package plugin generate-documentation'.
26+
--additional-docc-arguments <args...> Extra arguments forwarded to 'swift package plugin generate-documentation'.
27+
Consumes all remaining tokens until the next known option
28+
(--no-analyze, -h, --help) or end of arguments.
29+
-h, --help Show this help message.
30+
EOF
31+
}
32+
33+
is_known_option() {
34+
case "$1" in
35+
--no-analyze|--additional-docc-arguments|-h|--help)
36+
return 0
37+
;;
38+
*)
39+
return 1
40+
;;
41+
esac
42+
}
43+
44+
analyze_flag="--analyze"
45+
additional_docc_arguments=""
46+
while [[ $# -gt 0 ]]; do
47+
case "$1" in
48+
--no-analyze)
49+
analyze_flag=""
50+
shift
51+
;;
52+
--additional-docc-arguments)
53+
shift
54+
collected=()
55+
while [[ $# -gt 0 ]] && ! is_known_option "$1"; do
56+
collected+=("$1")
57+
shift
58+
done
59+
additional_docc_arguments="${collected[*]}"
60+
;;
61+
-h|--help)
62+
usage
63+
exit 0
64+
;;
65+
*)
66+
error "Unknown argument: $1"
67+
usage >&2
68+
exit 2
69+
;;
70+
esac
71+
done
72+
2073
if [ ! -f .spi.yml ]; then
21-
log "No '.spi.yml' found, no documentation targets to check."
22-
exit 0
74+
fatal "No '.spi.yml' found. Failing as there is no documentation targets to check. Learn more at https://github.com/swiftlang/github-workflows/blob/main/docs/soundness-docs-check.md"
2375
fi
2476

2577
if ! command -v yq &> /dev/null; then
@@ -55,8 +107,9 @@ fi
55107
log "Checking documentation targets..."
56108
for target in $(yq -r '.builder.configs[].documentation_targets[]' .spi.yml); do
57109
log "Checking target $target..."
58-
# shellcheck disable=SC2086 # We explicitly want to explode "$ADDITIONAL_DOCC_ARGUMENTS" into multiple arguments.
59-
swift package plugin generate-documentation --target "$target" --warnings-as-errors --analyze $ADDITIONAL_DOCC_ARGUMENTS
110+
target_docc_arguments=$(yq ".builder.configs[] | select(.documentation_targets[] == \"${target}\") | .custom_documentation_parameters[]" .spi.yml)
111+
# shellcheck disable=SC2086 # We explicitly want to explode "$analyze_flag", "$additional_docc_arguments" and "$target_docc_arguments" into multiple arguments.
112+
swift package plugin generate-documentation --target "$target" --warnings-as-errors $analyze_flag $additional_docc_arguments $target_docc_arguments
60113
done
61114

62115
log "✅ Found no documentation issues."

.github/workflows/soundness.yml

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ on:
3131
type: string
3232
description: "Additional arguments that should be passed to docc"
3333
default: ""
34+
docs_check_analyze:
35+
type: boolean
36+
description: "Boolean to pass --analyze to the docs check. Defaults to true."
37+
default: true
3438
docs_check_macos_enabled:
3539
type: boolean
3640
description: "Boolean to enable the macOS docs check job. Defaults to false."
@@ -51,6 +55,10 @@ on:
5155
type: string
5256
description: "Additional arguments that should be passed to docc for the macOS docs check job."
5357
default: ""
58+
docs_check_macos_analyze:
59+
type: boolean
60+
description: "Boolean to pass --analyze to the macOS docs check. Defaults to true."
61+
default: true
5462
unacceptable_language_check_enabled:
5563
type: boolean
5664
description: "Boolean to enable the acceptable language check job. Defaults to true."
@@ -187,8 +195,14 @@ jobs:
187195
- name: Run documentation check
188196
env:
189197
ADDITIONAL_DOCC_ARGUMENTS: ${{ inputs.docs_check_additional_arguments }}
198+
DOCC_ANALYZE: ${{ inputs.docs_check_analyze }}
190199
SCRIPT_ROOT: ${{ steps.script_path.outputs.root }}
191-
run: ${SCRIPT_ROOT}/.github/workflows/scripts/check-docs.sh
200+
run: |
201+
analyze_arg=""
202+
if [[ "${DOCC_ANALYZE}" != "true" ]]; then
203+
analyze_arg="--no-analyze"
204+
fi
205+
"${SCRIPT_ROOT}/.github/workflows/scripts/check-docs.sh" ${analyze_arg} --additional-docc-arguments ${ADDITIONAL_DOCC_ARGUMENTS}
192206
193207
docs-check-macos:
194208
name: Documentation check (macOS)
@@ -226,8 +240,14 @@ jobs:
226240
- name: Run documentation check
227241
env:
228242
ADDITIONAL_DOCC_ARGUMENTS: ${{ inputs.docs_check_macos_additional_arguments }}
243+
DOCC_ANALYZE: ${{ inputs.docs_check_macos_analyze }}
229244
SCRIPT_ROOT: ${{ steps.script_path.outputs.root }}
230-
run: ${SCRIPT_ROOT}/.github/workflows/scripts/check-docs.sh
245+
run: |
246+
analyze_arg=""
247+
if [[ "${DOCC_ANALYZE}" != "true" ]]; then
248+
analyze_arg="--no-analyze"
249+
fi
250+
"${SCRIPT_ROOT}/.github/workflows/scripts/check-docs.sh" ${analyze_arg} --additional-docc-arguments ${ADDITIONAL_DOCC_ARGUMENTS}
231251
232252
unacceptable-language-check:
233253
name: Unacceptable language check

docs/pr-dependency-workflow.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@ permissions:
2929
3030
jobs:
3131
check_dependencies:
32-
uses: swiftlang/github-workflows/.github/workflows/github_actions_dependencies.yml.yml@<to-be-updated>
32+
uses: swiftlang/github-workflows/.github/workflows/github_actions_dependencies.yml@<to-be-updated>
3333
```

docs/soundness-docs-check.md

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# Documentation Check
2+
3+
The Soundness workflow can verify that your Swift package's [DocC](https://www.swift.org/documentation/docc/) documentation builds without warnings. Two jobs are available:
4+
5+
- **`docs-check`** — runs on Linux. Enabled by default.
6+
- **`docs-check-macos`** — runs on a self-hosted macOS runner. Opt-in.
7+
8+
Running both lets you catch documentation issues that only surface on one toolchain.
9+
10+
Documentation warnings (and, by default, DocC analyzer findings) cause the job to fail.
11+
12+
## Requirements
13+
14+
For either job to run, your repository needs:
15+
16+
1. A `Package.swift` (or any `Package*.swift`) at the repository root.
17+
2. A `.spi.yml` at the repository root listing the targets to document. Read the [official documentation](https://swiftpackageindex.com/SwiftPackageIndex/SPIManifest/1.12.0/documentation/spimanifest/commonusecases) on how to generate the `.spi.yml`. For example:
18+
19+
```yaml
20+
version: 1
21+
builder:
22+
configs:
23+
- documentation_targets: [MyLibrary, MyOtherLibrary]
24+
custom_documentation_parameters:
25+
- --include-extended-types
26+
```
27+
28+
Targets listed under `documentation_targets` must match real SwiftPM target names. Any `custom_documentation_parameters` are forwarded to DocC for that group of targets.
29+
30+
You do not need to add `swift-docc-plugin` to your package — CI provides it for you.
31+
32+
## Enabling the check
33+
34+
Add (or extend) a workflow file under `.github/workflows/` in your repository:
35+
36+
```yaml
37+
name: Pull request
38+
39+
on:
40+
pull_request:
41+
branches: [main]
42+
43+
jobs:
44+
soundness:
45+
name: Soundness
46+
uses: swiftlang/github-workflows/.github/workflows/soundness.yml@<to-be-updated>>
47+
with:
48+
docs_check_enabled: true
49+
```
50+
51+
This enables the Linux documentation check along with the other soundness checks. The macOS variant remains off unless you opt in.
52+
53+
## Configuration
54+
55+
### Linux job (`docs-check`)
56+
57+
| Input | Type | Default | Description |
58+
|---|---|---|---|
59+
| `docs_check_enabled` | boolean | `true` | Enable or disable the job. |
60+
| `docs_check_container_image` | string | `swift:6.2-noble` | Docker image used to run the check. |
61+
| `docs_check_additional_arguments` | string | `""` | Extra arguments to pass to DocC. |
62+
| `docs_check_analyze` | boolean | `true` | Set to `false` to skip DocC's analyzer pass. |
63+
| `linux_pre_build_command` | string | `""` | Shell command to run before the check (e.g., installing system dependencies). |
64+
65+
### macOS job (`docs-check-macos`)
66+
67+
| Input | Type | Default | Description |
68+
|---|---|---|---|
69+
| `docs_check_macos_enabled` | boolean | `false` | Enable or disable the job. |
70+
| `docs_check_macos_version` | string | `tahoe` | macOS version label of the runner to target. |
71+
| `docs_check_macos_arch` | string | `ARM64` | Architecture label of the runner to target. |
72+
| `docs_check_macos_xcode_version` | string | `26.0` | Xcode version to use. |
73+
| `docs_check_macos_additional_arguments` | string | `""` | Extra arguments to pass to DocC. |
74+
| `docs_check_macos_analyze` | boolean | `true` | Set to `false` to skip DocC's analyzer pass. |
75+
76+
The macOS job requires a self-hosted runner registered with the label set `[self-hosted, macos, <version>, <arch>]`.
77+
78+
## Common scenarios
79+
80+
### Enable the macOS check
81+
82+
```yaml
83+
jobs:
84+
soundness:
85+
uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main
86+
with:
87+
docs_check_macos_enabled: true
88+
docs_check_macos_version: "tahoe"
89+
docs_check_macos_arch: "ARM64"
90+
docs_check_macos_xcode_version: "26.0"
91+
```
92+
93+
### Pin a different Swift toolchain or pass extra DocC flags
94+
95+
```yaml
96+
jobs:
97+
soundness:
98+
uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main
99+
with:
100+
docs_check_container_image: "swift:nightly-noble"
101+
docs_check_additional_arguments: "--include-extended-types"
102+
linux_pre_build_command: "apt-get update && apt-get install -y libxml2-dev"
103+
```
104+
105+
### Skip the DocC analyzer
106+
107+
```yaml
108+
jobs:
109+
soundness:
110+
uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main
111+
with:
112+
docs_check_analyze: false
113+
```
114+
115+
### Disable the check
116+
117+
If your package has no documentation targets, disable the job rather than letting it fail on a missing `.spi.yml`:
118+
119+
```yaml
120+
jobs:
121+
soundness:
122+
uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main
123+
with:
124+
docs_check_enabled: false
125+
```
126+
127+
## Troubleshooting
128+
129+
| Symptom | Likely cause |
130+
|---|---|
131+
| `No '.spi.yml' found.` | Add a `.spi.yml` at the repo root, or disable the job. |
132+
| `Package.swift not found.` | The check expects a SwiftPM package at the repo root. |
133+
| Warnings cause the job to fail. | Intentional. Resolve the DocC warnings, or pass DocC flags via `.spi.yml`'s `custom_documentation_parameters` to suppress them. |
134+
| macOS job stays queued. | No self-hosted runner matches the requested labels. Verify the `version` and `arch` inputs against your runner inventory. |
135+
| macOS job cannot find Xcode. | The requested Xcode version is not installed on the runner. |

tests/TestPackage/.spi.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
version: 1
2+
builder:
3+
configs:
4+
- documentation_targets:
5+
- theDocs

tests/TestPackage/Package.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ let package = Package(
1818
name: "Target1Tests",
1919
dependencies: ["Target1"]
2020
),
21+
.target(name: "theDocs"),
2122
]
2223
)

tests/TestPackage/Sources/theDocs/theDocs.swift

Whitespace-only changes.

0 commit comments

Comments
 (0)