Skip to content

Commit f9fc0f9

Browse files
committed
docs: switch to actions/deploy-pages — combined artifact approach (#31)
Replace peaceiris/actions-gh-pages (third-party deploy) with official GitHub Actions Pages deployment (actions/deploy-pages), satisfying the 'no third-party deploy service' acceptance criterion of issue #31. Strategy: - Pages source: GitHub Actions (actions/deploy-pages) - gh-pages branch: versioned snapshot storage only (not served directly) - deploy job: assembles a combined artifact — latest docs at the root + each vX/ snapshot fetched from the gh-pages storage branch — then uploads with actions/upload-pages-artifact + deploys via actions/deploy-pages (both pinned to commit SHAs) - snapshot job: stores the versioned build in gh-pages branch using plain git worktree (no peaceiris); removes [skip ci] from the versions.json commit so the push to main re-triggers the deploy job and the new snapshot is immediately included in the Pages artifact All actions pinned: actions/upload-pages-artifact 56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 actions/deploy-pages d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 (others unchanged from PR #39)
1 parent 989a679 commit f9fc0f9

1 file changed

Lines changed: 86 additions & 38 deletions

File tree

.github/workflows/docs.yml

Lines changed: 86 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,20 @@ on:
1515
- "v[0-9]*.0.0"
1616
workflow_dispatch:
1717

18-
# Deployment strategy: single mechanism — peaceiris/actions-gh-pages (gh-pages branch).
19-
# • latest docs → pushed to gh-pages root (keep_files: true preserves snapshots)
20-
# • versioned snapshot → pushed to gh-pages/<major>/ on major release tags
21-
# GitHub Pages must be configured to serve from the gh-pages branch (not GitHub Actions).
22-
#
23-
# Snapshot job needs contents write to push to gh-pages and commit versions.json back to main.
18+
# Deployment strategy: GitHub Actions Pages source (actions/deploy-pages — official, no third party).
19+
# • gh-pages branch = versioned snapshot STORAGE only (not served directly by Pages)
20+
# • Every deploy job assembles a combined artifact:
21+
# - latest docs built from main at the artifact root
22+
# - each vX/ snapshot from the gh-pages branch merged in
23+
# → single artifact deployed via actions/deploy-pages
24+
# • Snapshot job stores the built snapshot in gh-pages branch via plain git,
25+
# then pushes the updated versions.json to main (no [skip ci]) which
26+
# re-triggers the deploy job to include the new snapshot immediately.
27+
# Requires: Settings → Pages → Source: GitHub Actions.
2428
permissions:
2529
contents: write
30+
pages: write
31+
id-token: write
2632

2733
# Only one concurrent deployment for the same ref; cancel outdated runs.
2834
concurrency:
@@ -31,17 +37,29 @@ concurrency:
3137

3238
jobs:
3339
# ── Deploy (latest) ─────────────────────────────────────────────────────────
34-
# Builds docs and pushes them to the gh-pages root.
35-
# keep_files: true ensures versioned snapshots (v1/, v2/ …) are not wiped.
36-
# Requires: Settings → Pages → Source: Deploy from a branch → gh-pages / root.
40+
# Assembles a combined Pages artifact:
41+
# 1. Builds the latest docs (base: /github-code-search/)
42+
# 2. Merges existing versioned snapshots from the gh-pages storage branch
43+
# into the artifact (docs/.vitepress/dist/vX/ for each stored version)
44+
# 3. Uploads the artifact and deploys via actions/deploy-pages
45+
# Requires: Settings → Pages → Source: GitHub Actions.
3746
deploy:
38-
name: Deploy docs (latest)
47+
name: Build and deploy docs
3948
if: github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch'
4049
runs-on: ubuntu-latest
50+
permissions:
51+
pages: write
52+
id-token: write
53+
environment:
54+
name: github-pages
55+
url: ${{ steps.deploy.outputs.page_url }}
4156

4257
steps:
4358
- name: Checkout
4459
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
60+
with:
61+
# Needed to fetch the gh-pages storage branch for versioned snapshots.
62+
fetch-depth: 0
4563

4664
- name: Setup Bun
4765
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2.1.2
@@ -51,24 +69,43 @@ jobs:
5169
- name: Install dependencies
5270
run: bun install --frozen-lockfile
5371

54-
- name: Build docs
72+
- name: Build latest docs
5573
run: bun run docs:build
5674
# Base URL: /github-code-search/ (default in config.mts)
5775

58-
- name: Publish to gh-pages root
59-
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d231e62369c1b474e # v4.0.0
76+
- name: Merge versioned snapshots from gh-pages storage
77+
run: |
78+
if git ls-remote --heads origin gh-pages | grep -q gh-pages; then
79+
git fetch origin gh-pages
80+
# Copy each vX/ directory from the storage branch into the artifact root.
81+
for entry in $(git ls-tree --name-only origin/gh-pages); do
82+
if echo "$entry" | grep -qE '^v[0-9]+$'; then
83+
echo "Merging snapshot: $entry"
84+
mkdir -p "docs/.vitepress/dist/$entry"
85+
git archive origin/gh-pages "$entry" | tar -x -C docs/.vitepress/dist/
86+
fi
87+
done
88+
else
89+
echo "No gh-pages branch yet — skipping snapshot merge"
90+
fi
91+
92+
- name: Upload Pages artifact
93+
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1
6094
with:
61-
github_token: ${{ secrets.GITHUB_TOKEN }}
62-
publish_dir: docs/.vitepress/dist
63-
# Preserve versioned snapshots already pushed to gh-pages (v1/, v2/ …)
64-
keep_files: true
95+
path: docs/.vitepress/dist
96+
97+
- name: Deploy to GitHub Pages
98+
id: deploy
99+
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5
65100

66101
# ── Snapshot (versioned) ────────────────────────────────────────────────────
67102
# Triggered by a major release tag (e.g. v2.0.0).
68-
# Builds docs with a versioned base URL (/github-code-search/v2/) and publishes
69-
# the static output to the gh-pages branch under /v2/.
70-
# Also appends the new entry to docs/public/versions.json on main so that
71-
# future deployments expose the version in the nav dropdown.
103+
# 1. Builds docs with a versioned base URL (/github-code-search/v2/).
104+
# 2. Stores the output in the gh-pages branch under /v2/ using plain git
105+
# (no third-party action). The gh-pages branch is storage only — Pages
106+
# still points to GitHub Actions; the deploy job merges snapshots in.
107+
# 3. Prepends the entry to versions.json on main WITHOUT [skip ci], which
108+
# re-triggers the deploy job so the new snapshot is live immediately.
72109
#
73110
# Convention: only tags matching vX.0.0 (major bumps) trigger a snapshot.
74111
# Patch and minor releases update the main docs in-place via the deploy job.
@@ -83,15 +120,13 @@ jobs:
83120
- name: Checkout
84121
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
85122
with:
86-
# Full history needed to push the versions.json commit back to main.
123+
# Full history needed to push to gh-pages and commit versions.json to main.
87124
fetch-depth: 0
88125

89126
- name: Extract major version from tag
90127
id: ver
91128
run: |
92-
TAG="${GITHUB_REF_NAME}" # e.g. v2.0.0
93-
MAJOR="$(echo "$TAG" | cut -d. -f1)" # e.g. v2
94-
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
129+
MAJOR="$(echo "$GITHUB_REF_NAME" | cut -d. -f1)" # e.g. v2
95130
echo "major=$MAJOR" >> "$GITHUB_OUTPUT"
96131
97132
- name: Setup Bun
@@ -108,30 +143,43 @@ jobs:
108143
VITEPRESS_BASE: /github-code-search/${{ steps.ver.outputs.major }}/
109144
run: bun run docs:build
110145

111-
- name: Publish snapshot to gh-pages
112-
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d231e62369c1b474e # v4.0.0
113-
with:
114-
github_token: ${{ secrets.GITHUB_TOKEN }}
115-
publish_dir: docs/.vitepress/dist
116-
destination_dir: ${{ steps.ver.outputs.major }}
117-
# Preserve all existing pages (other versions, latest, etc.)
118-
keep_files: true
146+
- name: Store snapshot in gh-pages branch
147+
run: |
148+
MAJOR="${{ steps.ver.outputs.major }}"
149+
git config user.name "github-actions[bot]"
150+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
151+
# Set up the gh-pages worktree (create orphan branch if it doesn't exist yet).
152+
if git ls-remote --heads origin gh-pages | grep -q gh-pages; then
153+
git fetch origin gh-pages
154+
git worktree add /tmp/gh-pages-storage origin/gh-pages
155+
else
156+
git worktree add --orphan -b gh-pages /tmp/gh-pages-storage
157+
touch /tmp/gh-pages-storage/.nojekyll # prevent Jekyll processing
158+
fi
159+
# Copy the built snapshot into its versioned directory.
160+
rm -rf "/tmp/gh-pages-storage/$MAJOR"
161+
cp -r docs/.vitepress/dist "/tmp/gh-pages-storage/$MAJOR"
162+
# Commit and push.
163+
cd /tmp/gh-pages-storage
164+
git add .
165+
git diff --staged --quiet || git commit -m "docs: store snapshot $MAJOR [skip ci]"
166+
git push origin gh-pages
119167
120168
- name: Prepend new version entry to versions.json
121169
run: |
122170
MAJOR="${{ steps.ver.outputs.major }}"
123-
# Link is relative to the VitePress base — VitePress will not add the base a
124-
# second time (same convention as the initial "v1 (latest)" entry: link "/")
125171
LINK="/${MAJOR}/"
126-
# Idempotent: skip if the entry already exists
172+
# Idempotentskip if the entry already exists.
127173
jq --arg text "$MAJOR" --arg link "$LINK" \
128174
'if any(.[]; .link == $link) then . else [{"text": $text, "link": $link}] + . end' \
129175
docs/public/versions.json > /tmp/versions_new.json
130176
mv /tmp/versions_new.json docs/public/versions.json
131177
132-
- name: Commit updated versions.json to main
178+
- name: Commit versions.json to main
133179
uses: stefanzweifel/git-auto-commit-action@8621497c8c39c72f3e2a999a26b4ca1b5590082e # v5.0.1
134180
with:
135-
commit_message: "docs: add ${{ steps.ver.outputs.major }} to versions.json [skip ci]"
181+
# No [skip ci] — the push to main matches paths: docs/** and re-triggers
182+
# the deploy job, which merges the new snapshot into the Pages artifact.
183+
commit_message: "docs: add ${{ steps.ver.outputs.major }} to versions.json"
136184
file_pattern: docs/public/versions.json
137185
branch: main

0 commit comments

Comments
 (0)