Skip to content

Commit eae5369

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 eae5369

9 files changed

Lines changed: 290 additions & 9 deletions

File tree

.github/workflows/pull_request.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,6 @@ jobs:
9595
uses: ./.github/workflows/soundness.yml
9696
with:
9797
api_breakage_check_enabled: false
98+
docs_check_enabled: true
99+
docs_check_macos_enabled: true
98100
license_header_check_project_name: "Swift.org"

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

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

20-
if [ ! -f .spi.yml ]; then
21-
log "No '.spi.yml' found, no documentation targets to check."
22-
exit 0
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+
--doc-targets target [target2 ...] The documentation targets to build.
27+
--additional-docc-arguments [arg ...] Extra arguments forwarded to 'swift package plugin generate-documentation'.
28+
-h, --help Show this help message.
29+
EOF
30+
}
31+
32+
is_known_option() {
33+
case "$1" in
34+
--no-analyze|--additional-docc-arguments|--doc-targets|-h|--help)
35+
return 0
36+
;;
37+
*)
38+
return 1
39+
;;
40+
esac
41+
}
42+
43+
analyze_flag="--analyze"
44+
additional_docc_arguments=""
45+
docs_targets=""
46+
while [[ $# -gt 0 ]]; do
47+
case "$1" in
48+
--no-analyze)
49+
analyze_flag=""
50+
shift
51+
;;
52+
--doc-targets)
53+
shift
54+
collected=()
55+
while [[ $# -gt 0 ]] && ! is_known_option "$1"; do
56+
collected+=("$1")
57+
shift
58+
done
59+
docs_targets="${collected[*]}"
60+
;;
61+
--additional-docc-arguments)
62+
shift
63+
collected=()
64+
while [[ $# -gt 0 ]] && ! is_known_option "$1"; do
65+
collected+=("$1")
66+
shift
67+
done
68+
additional_docc_arguments="${collected[*]}"
69+
;;
70+
-h|--help)
71+
usage
72+
exit 0
73+
;;
74+
*)
75+
error "Unknown argument: $1"
76+
usage >&2
77+
exit 2
78+
;;
79+
esac
80+
done
81+
82+
if [ -z "${docs_targets}" ] ; then
83+
if [ ! -f .spi.yml ]; then
84+
log "No '.spi.yml' found, no documentation targets to check."
85+
exit 0
86+
fi
2387
fi
2488

2589
if ! command -v yq &> /dev/null; then
@@ -29,6 +93,10 @@ if ! command -v yq &> /dev/null; then
2993
esac
3094
fi
3195

96+
if [ -z "${docs_targets}" ] ; then
97+
docs_targets=$(yq ".builder.configs[] | select(.documentation_targets[] != \"\") | .documentation_targets[]" .spi.yml)y
98+
fi
99+
32100
package_files=$(find . -maxdepth 1 -name 'Package*.swift')
33101
if [ -z "$package_files" ]; then
34102
fatal "Package.swift not found. Please ensure you are running this script from the root of a Swift package."
@@ -53,10 +121,10 @@ EOF
53121
fi
54122

55123
log "Checking documentation targets..."
56-
for target in $(yq -r '.builder.configs[].documentation_targets[]' .spi.yml); do
124+
for target in ${docs_targets}; do
57125
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
126+
# shellcheck disable=SC2086 # We explicitly want to explode "$analyze_flag" an "$additional_docc_arguments"d into multiple arguments.
127+
swift package plugin generate-documentation --target "$target" --warnings-as-errors $analyze_flag $additional_docc_arguments
60128
done
61129

62130
log "✅ Found no documentation issues."

.github/workflows/soundness.yml

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ on:
3131
type: string
3232
description: "Additional arguments that should be passed to docc"
3333
default: ""
34+
docs_check_targets:
35+
type: string
36+
description: "List of targets to check for documentation. Defaults to empty string."
37+
default: ""
38+
docs_check_analyze:
39+
type: boolean
40+
description: "Boolean to pass --analyze to the docs check. Defaults to true."
41+
default: true
3442
docs_check_macos_enabled:
3543
type: boolean
3644
description: "Boolean to enable the macOS docs check job. Defaults to false."
@@ -51,6 +59,14 @@ on:
5159
type: string
5260
description: "Additional arguments that should be passed to docc for the macOS docs check job."
5361
default: ""
62+
docs_check_macos_targets:
63+
type: string
64+
description: "List of targets to check for documentation. Defaults to empty string."
65+
default: ""
66+
docs_check_macos_analyze:
67+
type: boolean
68+
description: "Boolean to pass --analyze to the macOS docs check. Defaults to true."
69+
default: true
5470
unacceptable_language_check_enabled:
5571
type: boolean
5672
description: "Boolean to enable the acceptable language check job. Defaults to true."
@@ -187,8 +203,19 @@ jobs:
187203
- name: Run documentation check
188204
env:
189205
ADDITIONAL_DOCC_ARGUMENTS: ${{ inputs.docs_check_additional_arguments }}
206+
DOCC_ANALYZE: ${{ inputs.docs_check_analyze }}
207+
DOCS_TARGETS: ${{ inputs.docs_check_targets}}
190208
SCRIPT_ROOT: ${{ steps.script_path.outputs.root }}
191-
run: ${SCRIPT_ROOT}/.github/workflows/scripts/check-docs.sh
209+
run: |
210+
analyze_arg=""
211+
doc_target_arg=""
212+
if [[ "${DOCS_TARGETS}" != "" ]] ; then
213+
doc_target_arg="--doc-targets ${DOCS_TARGETS}"
214+
fi
215+
if [[ "${DOCC_ANALYZE}" != "true" ]]; then
216+
analyze_arg="--no-analyze"
217+
fi
218+
"${SCRIPT_ROOT}/.github/workflows/scripts/check-docs.sh" ${analyze_arg} ${doc_target_arg} --additional-docc-arguments ${ADDITIONAL_DOCC_ARGUMENTS}
192219
193220
docs-check-macos:
194221
name: Documentation check (macOS)
@@ -226,8 +253,19 @@ jobs:
226253
- name: Run documentation check
227254
env:
228255
ADDITIONAL_DOCC_ARGUMENTS: ${{ inputs.docs_check_macos_additional_arguments }}
256+
DOCC_ANALYZE: ${{ inputs.docs_check_macos_analyze }}
257+
DOCS_TARGETS: ${{ inputs.docs_check_macos_targets}}
229258
SCRIPT_ROOT: ${{ steps.script_path.outputs.root }}
230-
run: ${SCRIPT_ROOT}/.github/workflows/scripts/check-docs.sh
259+
run: |
260+
analyze_arg=""
261+
doc_target_arg=""
262+
if [[ "${DOCS_TARGETS}" != "" ]] ; then
263+
doc_target_arg="--doc-targets ${DOCS_TARGETS}"
264+
fi
265+
if [[ "${DOCC_ANALYZE}" != "true" ]]; then
266+
analyze_arg="--no-analyze"
267+
fi
268+
"${SCRIPT_ROOT}/.github/workflows/scripts/check-docs.sh" ${analyze_arg} ${doc_target_arg} --additional-docc-arguments ${ADDITIONAL_DOCC_ARGUMENTS}
231269
232270
unacceptable-language-check:
233271
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: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
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_targets` | string | `""` | Space-separated list of documentation targets to check. When empty, the targets listed in `.spi.yml` are used. |
62+
| `docs_check_additional_arguments` | string | `""` | Extra arguments to pass to DocC. |
63+
| `docs_check_analyze` | boolean | `true` | Set to `false` to skip DocC's analyzer pass. |
64+
| `linux_pre_build_command` | string | `""` | Shell command to run before the check (e.g., installing system dependencies). |
65+
66+
### macOS job (`docs-check-macos`)
67+
68+
| Input | Type | Default | Description |
69+
|---|---|---|---|
70+
| `docs_check_macos_enabled` | boolean | `false` | Enable or disable the job. |
71+
| `docs_check_macos_version` | string | `tahoe` | macOS version label of the runner to target. |
72+
| `docs_check_macos_arch` | string | `ARM64` | Architecture label of the runner to target. |
73+
| `docs_check_macos_xcode_version` | string | `26.0` | Xcode version to use. |
74+
| `docs_check_macos_targets` | string | `""` | Space-separated list of documentation targets to check. When empty, the targets listed in `.spi.yml` are used. |
75+
| `docs_check_macos_additional_arguments` | string | `""` | Extra arguments to pass to DocC. |
76+
| `docs_check_macos_analyze` | boolean | `true` | Set to `false` to skip DocC's analyzer pass. |
77+
78+
The macOS job requires a self-hosted runner registered with the label set `[self-hosted, macos, <version>, <arch>]`.
79+
80+
## Common scenarios
81+
82+
### Enable the macOS check
83+
84+
```yaml
85+
jobs:
86+
soundness:
87+
uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main
88+
with:
89+
docs_check_macos_enabled: true
90+
docs_check_macos_version: "tahoe"
91+
docs_check_macos_arch: "ARM64"
92+
docs_check_macos_xcode_version: "26.0"
93+
```
94+
95+
### Check only specific targets
96+
97+
By default the check documents every target listed in `.spi.yml`. To override that list without editing `.spi.yml`, provide the target names explicitly:
98+
99+
```yaml
100+
jobs:
101+
soundness:
102+
uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main
103+
with:
104+
docs_check_targets: "MyLibrary MyOtherLibrary"
105+
```
106+
107+
### Pin a different Swift toolchain or pass extra DocC flags
108+
109+
```yaml
110+
jobs:
111+
soundness:
112+
uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main
113+
with:
114+
docs_check_container_image: "swift:nightly-noble"
115+
docs_check_additional_arguments: "--include-extended-types"
116+
linux_pre_build_command: "apt-get update && apt-get install -y libxml2-dev"
117+
```
118+
119+
### Skip the DocC analyzer
120+
121+
```yaml
122+
jobs:
123+
soundness:
124+
uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main
125+
with:
126+
docs_check_analyze: false
127+
```
128+
129+
### Disable the check
130+
131+
If your package has no documentation targets, disable the job rather than letting it fail on a missing `.spi.yml`:
132+
133+
```yaml
134+
jobs:
135+
soundness:
136+
uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main
137+
with:
138+
docs_check_enabled: false
139+
```
140+
141+
## Troubleshooting
142+
143+
| Symptom | Likely cause |
144+
|---|---|
145+
| `No '.spi.yml' found.` | Add a `.spi.yml` at the repo root, or disable the job. |
146+
| `Package.swift not found.` | The check expects a SwiftPM package at the repo root. |
147+
| 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. |
148+
| macOS job stays queued. | No self-hosted runner matches the requested labels. Verify the `version` and `arch` inputs against your runner inventory. |
149+
| 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
)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Document title
2+
3+
This is a sample document.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2026 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
func hello() {
14+
print("Hello, world!")
15+
}

0 commit comments

Comments
 (0)