Skip to content

Commit aaa0214

Browse files
committed
docs: add a script for automatic documentation deploy
1 parent 54d86f6 commit aaa0214

2 files changed

Lines changed: 342 additions & 0 deletions

File tree

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# .github/actions/build-docc/action.yml
2+
name: 'Build DocC Documentation'
3+
description: 'Builds Swift DocC documentation for multiple products and platforms'
4+
5+
inputs:
6+
products:
7+
description: 'Comma-separated list of product names (e.g., "ValidatorCore,ValidatorUI")'
8+
required: true
9+
docc-paths:
10+
description: 'Comma-separated list of .docc paths (e.g., "Sources/ValidatorCore/Validator.docc,Sources/ValidatorUI/ValidatorUI.docc")'
11+
required: false
12+
default: ''
13+
bundle-identifier-prefix:
14+
description: 'Bundle identifier prefix (e.g., "dev.validator")'
15+
required: false
16+
default: 'dev.package'
17+
bundle-version:
18+
description: 'Bundle version for documentation'
19+
required: false
20+
default: '1.0.0'
21+
platforms:
22+
description: 'Comma-separated list of platforms to build for (e.g., "iOS,macOS,watchOS,tvOS,visionOS")'
23+
required: false
24+
default: 'iOS,macOS,watchOS,tvOS,visionOS'
25+
output-path:
26+
description: 'Output directory for generated documentation'
27+
required: false
28+
default: './docs'
29+
hosting-base-path:
30+
description: 'Base path for static hosting (leave empty for root)'
31+
required: false
32+
default: ''
33+
34+
runs:
35+
using: 'composite'
36+
steps:
37+
- name: Setup Build Directories
38+
shell: bash
39+
run: |
40+
mkdir -p .build/symbol-graphs
41+
mkdir -p ${{ inputs.output-path }}
42+
43+
- name: Build Symbol Graphs
44+
shell: bash
45+
run: |
46+
IFS=',' read -ra PRODUCTS <<< "${{ inputs.products }}"
47+
IFS=',' read -ra PLATFORMS <<< "${{ inputs.platforms }}"
48+
49+
for PRODUCT in "${PRODUCTS[@]}"; do
50+
echo "Building symbol graphs for ${PRODUCT}"
51+
52+
for PLATFORM in "${PLATFORMS[@]}"; do
53+
echo " Platform: ${PLATFORM}"
54+
SYMBOL_DIR=".build/symbol-graphs/${PRODUCT}/${PLATFORM}"
55+
mkdir -p "${SYMBOL_DIR}"
56+
57+
xcodebuild build \
58+
-scheme "${PRODUCT}" \
59+
-destination "generic/platform=${PLATFORM}" \
60+
-derivedDataPath .deriveddata \
61+
DOCC_EXTRACT_EXTENSION_SYMBOLS=YES \
62+
OTHER_SWIFT_FLAGS="-Xfrontend -emit-symbol-graph -Xfrontend -emit-symbol-graph-dir -Xfrontend ${SYMBOL_DIR} -Xfrontend -emit-extension-block-symbols" \
63+
2>&1 | grep -v "note:" | grep -v "warning:" || true
64+
done
65+
done
66+
67+
- name: Generate Documentation
68+
shell: bash
69+
run: |
70+
IFS=',' read -ra PRODUCTS <<< "${{ inputs.products }}"
71+
IFS=',' read -ra DOCC_PATHS <<< "${{ inputs.docc-paths }}"
72+
73+
for i in "${!PRODUCTS[@]}"; do
74+
PRODUCT="${PRODUCTS[$i]}"
75+
DOCC_PATH=""
76+
77+
if [ ${#DOCC_PATHS[@]} -gt $i ]; then
78+
DOCC_PATH="${DOCC_PATHS[$i]}"
79+
fi
80+
81+
echo "Generating documentation for ${PRODUCT}"
82+
83+
BUNDLE_ID="${{ inputs.bundle-identifier-prefix }}.${PRODUCT}"
84+
85+
if [ -n "${DOCC_PATH}" ] && [ -d "${DOCC_PATH}" ]; then
86+
echo " Using .docc catalog: ${DOCC_PATH}"
87+
$(xcrun --find docc) convert "${DOCC_PATH}" \
88+
--fallback-display-name "${PRODUCT}" \
89+
--fallback-bundle-identifier "${BUNDLE_ID}" \
90+
--fallback-bundle-version "${{ inputs.bundle-version }}" \
91+
--output-dir "${PRODUCT}.doccarchive" \
92+
--additional-symbol-graph-dir ".build/symbol-graphs/${PRODUCT}"
93+
else
94+
echo " Generating from code comments only"
95+
$(xcrun --find docc) convert \
96+
--fallback-display-name "${PRODUCT}" \
97+
--fallback-bundle-identifier "${BUNDLE_ID}" \
98+
--fallback-bundle-version "${{ inputs.bundle-version }}" \
99+
--output-dir "${PRODUCT}.doccarchive" \
100+
--additional-symbol-graph-dir ".build/symbol-graphs/${PRODUCT}"
101+
fi
102+
103+
# Transform for static hosting
104+
if [ -n "${{ inputs.hosting-base-path }}" ]; then
105+
BASE_PATH="${{ inputs.hosting-base-path }}/${PRODUCT}"
106+
else
107+
BASE_PATH="${PRODUCT}"
108+
fi
109+
110+
$(xcrun --find docc) process-archive transform-for-static-hosting \
111+
"${PRODUCT}.doccarchive" \
112+
--output-path "${{ inputs.output-path }}/${PRODUCT}" \
113+
--hosting-base-path "${BASE_PATH}"
114+
115+
echo "✓ ${PRODUCT} documentation generated"
116+
done
117+
118+
- name: Cleanup Build Artifacts
119+
shell: bash
120+
if: always()
121+
run: |
122+
rm -rf .deriveddata
123+
rm -rf .build
124+
rm -rf *.doccarchive

.github/workflows/docs.yml

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
# .github/workflows/deploy-docc.yml
2+
name: Deploy DocC Documentation
3+
4+
on:
5+
push:
6+
branches: ["main"]
7+
pull_request:
8+
branches: ["main"]
9+
workflow_dispatch:
10+
11+
permissions:
12+
contents: write
13+
pages: write
14+
id-token: write
15+
actions: read
16+
17+
concurrency:
18+
group: "pages"
19+
cancel-in-progress: false
20+
21+
jobs:
22+
build-and-deploy:
23+
runs-on: macos-14
24+
steps:
25+
- name: Checkout
26+
uses: actions/checkout@v4
27+
28+
- name: Setup Xcode
29+
uses: maxim-lobanov/setup-xcode@v1
30+
with:
31+
xcode-version: latest-stable
32+
33+
- name: Get repository name
34+
id: repo-name
35+
run: echo "REPO_NAME=${GITHUB_REPOSITORY#*/}" >> $GITHUB_OUTPUT
36+
37+
- name: Build DocC Documentation
38+
uses: ./.github/actions/build-docc
39+
with:
40+
products: 'ValidatorCore,ValidatorUI'
41+
docc-paths: 'Sources/ValidatorCore/Validator.docc,Sources/ValidatorUI/ValidatorUI.docc'
42+
bundle-identifier-prefix: 'dev.validator'
43+
bundle-version: '1.0.0'
44+
platforms: 'iOS,macOS,watchOS,tvOS,visionOS'
45+
output-path: './docs'
46+
hosting-base-path: '${{ steps.repo-name.outputs.REPO_NAME }}'
47+
48+
- name: Create Index Page
49+
run: |
50+
cat > docs/index.html << 'EOF'
51+
<!DOCTYPE html>
52+
<html lang="en">
53+
<head>
54+
<meta charset="UTF-8">
55+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
56+
<title>Validator Documentation</title>
57+
<style>
58+
* {
59+
margin: 0;
60+
padding: 0;
61+
box-sizing: border-box;
62+
}
63+
body {
64+
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
65+
background: #f5f5f7;
66+
min-height: 100vh;
67+
display: flex;
68+
align-items: center;
69+
justify-content: center;
70+
padding: 40px 20px;
71+
color: #1d1d1f;
72+
}
73+
.container {
74+
max-width: 980px;
75+
width: 100%;
76+
}
77+
header {
78+
text-align: center;
79+
margin-bottom: 60px;
80+
}
81+
h1 {
82+
font-size: 56px;
83+
font-weight: 600;
84+
letter-spacing: -0.005em;
85+
line-height: 1.07143;
86+
margin-bottom: 8px;
87+
color: #1d1d1f;
88+
}
89+
.subtitle {
90+
font-size: 28px;
91+
font-weight: 400;
92+
line-height: 1.14286;
93+
color: #6e6e73;
94+
}
95+
.docs-grid {
96+
display: grid;
97+
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
98+
gap: 24px;
99+
margin-bottom: 40px;
100+
}
101+
.doc-card {
102+
background: white;
103+
border-radius: 18px;
104+
padding: 40px;
105+
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
106+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
107+
text-decoration: none;
108+
display: block;
109+
border: 1px solid rgba(0,0,0,0.06);
110+
}
111+
.doc-card:hover {
112+
transform: translateY(-4px);
113+
box-shadow: 0 12px 24px rgba(0,0,0,0.12);
114+
}
115+
.doc-card h2 {
116+
font-size: 32px;
117+
font-weight: 600;
118+
margin-bottom: 12px;
119+
color: #1d1d1f;
120+
letter-spacing: -0.003em;
121+
}
122+
.doc-card p {
123+
font-size: 17px;
124+
line-height: 1.47059;
125+
color: #6e6e73;
126+
margin-bottom: 20px;
127+
}
128+
.doc-card .link {
129+
font-size: 17px;
130+
color: #0071e3;
131+
font-weight: 400;
132+
display: inline-flex;
133+
align-items: center;
134+
}
135+
.doc-card .link::after {
136+
content: '→';
137+
margin-left: 8px;
138+
transition: transform 0.3s ease;
139+
}
140+
.doc-card:hover .link::after {
141+
transform: translateX(4px);
142+
}
143+
.module-badge {
144+
display: inline-block;
145+
background: #f5f5f7;
146+
color: #6e6e73;
147+
padding: 4px 12px;
148+
border-radius: 12px;
149+
font-size: 12px;
150+
font-weight: 600;
151+
letter-spacing: 0.5px;
152+
text-transform: uppercase;
153+
margin-bottom: 16px;
154+
}
155+
footer {
156+
text-align: center;
157+
padding-top: 40px;
158+
border-top: 1px solid rgba(0,0,0,0.08);
159+
margin-top: 40px;
160+
}
161+
footer p {
162+
font-size: 14px;
163+
color: #86868b;
164+
}
165+
@media (max-width: 768px) {
166+
h1 {
167+
font-size: 40px;
168+
}
169+
.subtitle {
170+
font-size: 21px;
171+
}
172+
.docs-grid {
173+
grid-template-columns: 1fr;
174+
}
175+
.doc-card {
176+
padding: 32px;
177+
}
178+
}
179+
</style>
180+
</head>
181+
<body>
182+
<div class="container">
183+
<header>
184+
<h1>Validator</h1>
185+
<p class="subtitle">Comprehensive documentation for Swift validation framework</p>
186+
</header>
187+
188+
<div class="docs-grid">
189+
<a href="ValidatorCore/documentation/validatorcore/" class="doc-card">
190+
<span class="module-badge">Core Module</span>
191+
<h2>ValidatorCore</h2>
192+
<p>Core validation functionality and rules for Swift applications. Contains base types, protocols, and validator implementations.</p>
193+
<span class="link">View documentation</span>
194+
</a>
195+
196+
<a href="ValidatorUI/documentation/validatorui/" class="doc-card">
197+
<span class="module-badge">UI Module</span>
198+
<h2>ValidatorUI</h2>
199+
<p>UI components and helpers for building validation interfaces. Ready-to-use solutions for SwiftUI and UIKit.</p>
200+
<span class="link">View documentation</span>
201+
</a>
202+
</div>
203+
204+
<footer>
205+
<p>Generated with Swift DocC</p>
206+
</footer>
207+
</div>
208+
</body>
209+
</html>
210+
EOF
211+
212+
- name: Deploy to gh-pages
213+
uses: peaceiris/actions-gh-pages@v3
214+
with:
215+
github_token: ${{ secrets.GITHUB_TOKEN }}
216+
publish_dir: ./docs
217+
publish_branch: gh-pages
218+
force_orphan: true

0 commit comments

Comments
 (0)