Skip to content

Commit ff5a0fa

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

2 files changed

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

0 commit comments

Comments
 (0)