11name : Docs
22
33on :
4- push :
4+ # Trigger when CI completes successfully on master
5+ workflow_run :
6+ workflows : ["CI"]
7+ types : [completed]
58 branches : [master]
9+ # Trigger on version tags for release docs
10+ push :
611 tags : ['v*']
712 workflow_dispatch :
813
914permissions :
1015 contents : read
1116 pages : write
1217 id-token : write
18+ actions : read # Required to download artifacts from other workflows
1319
1420concurrency :
1521 group : docs
@@ -18,8 +24,15 @@ concurrency:
1824jobs :
1925 build :
2026 runs-on : ubuntu-latest
27+ # Only run if CI succeeded (for workflow_run trigger) or if triggered by tag/manual
28+ if : >
29+ github.event_name != 'workflow_run' ||
30+ github.event.workflow_run.conclusion == 'success'
2131 steps :
2232 - uses : actions/checkout@v4
33+ with :
34+ # For workflow_run, checkout the commit that triggered CI
35+ ref : ${{ github.event.workflow_run.head_sha || github.ref }}
2336
2437 - name : Install uv
2538 uses : astral-sh/setup-uv@v4
4255 DOCS_VERSION : ${{ steps.version.outputs.version }}
4356 run : uv run sphinx-build -b html docs docs/_build/html
4457
45- - name : Upload artifact
58+ - name : Upload docs artifact
4659 uses : actions/upload-artifact@v4
4760 with :
4861 name : docs-${{ steps.version.outputs.version }}
@@ -55,20 +68,66 @@ jobs:
5568 name : github-pages
5669 url : ${{ steps.deployment.outputs.page_url }}
5770 steps :
58- - name : Download current docs
71+ - name : Determine version
72+ id : version
73+ run : |
74+ if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
75+ VERSION="${GITHUB_REF#refs/tags/v}"
76+ else
77+ VERSION="latest"
78+ fi
79+ echo "version=$VERSION" >> $GITHUB_OUTPUT
80+
81+ - name : Download docs artifact
5982 uses : actions/download-artifact@v4
6083 with :
61- pattern : docs-*
62- path : site/
63- merge-multiple : false
84+ name : docs-${{ steps.version.outputs.version }}
85+ path : deploy/${{ steps.version.outputs.version }}/
86+
87+ # Download CI reports for latest docs (from the CI workflow that triggered us)
88+ - name : Download CI artifacts
89+ if : github.event_name == 'workflow_run' && steps.version.outputs.version == 'latest'
90+ uses : actions/download-artifact@v4
91+ with :
92+ name : coverage-report
93+ path : deploy/reports/coverage/
94+ github-token : ${{ github.token }}
95+ run-id : ${{ github.event.workflow_run.id }}
96+
97+ - name : Download mypy report
98+ if : github.event_name == 'workflow_run' && steps.version.outputs.version == 'latest'
99+ uses : actions/download-artifact@v4
100+ with :
101+ name : mypy-report
102+ path : deploy/reports/mypy/
103+ github-token : ${{ github.token }}
104+ run-id : ${{ github.event.workflow_run.id }}
64105
65- - name : Prepare site structure
106+ - name : Create reports index
107+ if : github.event_name == 'workflow_run' && steps.version.outputs.version == 'latest'
66108 run : |
67- VERSION=$(ls site/ | sed 's/docs-//')
68- mkdir -p deploy/$VERSION
69- cp -r site/docs-$VERSION/* deploy/$VERSION/
109+ cat > deploy/reports/index.html << 'EOF'
110+ <!DOCTYPE html>
111+ <html>
112+ <head>
113+ <title>kdbxtool Reports</title>
114+ <style>
115+ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
116+ h1 { color: #333; }
117+ a { display: block; padding: 15px; margin: 10px 0; background: #f5f5f5; border-radius: 8px; text-decoration: none; color: #0066cc; }
118+ a:hover { background: #e8e8e8; }
119+ </style>
120+ </head>
121+ <body>
122+ <h1>kdbxtool Reports</h1>
123+ <a href="coverage/htmlcov/">Test Coverage Report</a>
124+ <a href="mypy/">Type Coverage Report (mypy)</a>
125+ </body>
126+ </html>
127+ EOF
70128
71- # Create redirect index at root
129+ - name : Create root redirect
130+ run : |
72131 cat > deploy/index.html << 'EOF'
73132 <!DOCTYPE html>
74133 <html>
@@ -77,15 +136,38 @@ jobs:
77136 </html>
78137 EOF
79138
80- - name : Download existing pages (if any )
139+ - name : Download existing pages (preserve other versions )
81140 continue-on-error : true
141+ env :
142+ GH_TOKEN : ${{ github.token }}
82143 run : |
83- # Fetch existing gh-pages content to preserve other versions
84- git clone --depth 1 --branch gh-pages \
85- https://github.com/${{ github.repository }}.git existing || true
86- if [ -d existing ]; then
87- cp -rn existing/* deploy/ 2>/dev/null || true
88- rm -rf existing
144+ # Get the latest pages deployment and download its artifact
145+ # This preserves other doc versions when deploying a new one
146+ ARTIFACT_ID=$(gh api repos/${{ github.repository }}/actions/artifacts \
147+ --jq '[.artifacts[] | select(.name == "github-pages")] | first | .id' 2>/dev/null || echo "")
148+
149+ if [ -n "$ARTIFACT_ID" ] && [ "$ARTIFACT_ID" != "null" ]; then
150+ echo "Downloading existing pages artifact $ARTIFACT_ID..."
151+ gh api repos/${{ github.repository }}/actions/artifacts/$ARTIFACT_ID/zip > existing.zip || true
152+ if [ -f existing.zip ]; then
153+ unzip -o existing.zip -d existing_tar/ || true
154+ if [ -f existing_tar/artifact.tar ]; then
155+ mkdir -p existing/
156+ tar -xf existing_tar/artifact.tar -C existing/ || true
157+ # Copy existing versions (but not the one we're deploying)
158+ for dir in existing/*/; do
159+ dirname=$(basename "$dir")
160+ if [ "$dirname" != "${{ steps.version.outputs.version }}" ] && [ "$dirname" != "reports" ]; then
161+ cp -rn "$dir" deploy/ 2>/dev/null || true
162+ fi
163+ done
164+ # Preserve reports if we're deploying a versioned release (not latest)
165+ if [ "${{ steps.version.outputs.version }}" != "latest" ] && [ -d existing/reports ]; then
166+ cp -rn existing/reports deploy/ 2>/dev/null || true
167+ fi
168+ fi
169+ rm -rf existing_tar existing existing.zip
170+ fi
89171 fi
90172
91173 - name : Setup Pages
0 commit comments