docs: versioning strategy — CI snapshot + deploy workflow#39
docs: versioning strategy — CI snapshot + deploy workflow#39shouze merged 2 commits intofeat/vitepress-docsfrom
Conversation
- .github/workflows/docs.yml: new workflow — 3 jobs
- build: bun docs:build + upload-pages-artifact (triggered on main push)
- deploy: actions/deploy-pages@v4 (triggered on main push)
- snapshot: triggered on vX.0.0 tags — builds with VITEPRESS_BASE,
deploys to gh-pages under /vX/ via peaceiris/actions-gh-pages,
prepends entry to versions.json via stefanzweifel/git-auto-commit-action
- All third-party actions pinned to commit SHAs
- docs/.vitepress/config.mts: base reads process.env.VITEPRESS_BASE
with fallback to /github-code-search/ for regular main-branch deploys
- docs/public/versions.json already initialised with v1 (latest) — no change needed
- Covers issue #31 (GitHub Pages CI/CD deploy) as prerequisite
There was a problem hiding this comment.
Pull request overview
Introduces a documentation versioning/deployment strategy for the VitePress site, aiming to continuously deploy main as “latest” while snapshotting major releases (vX.0.0) to versioned paths and keeping the version dropdown data in sync.
Changes:
- Add a new GitHub Actions workflow to build/deploy latest docs and publish major-release snapshots.
- Make the VitePress
baseconfigurable viaVITEPRESS_BASEfor versioned snapshot builds. - Update docs config comments to document the intended versioning convention.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
docs/.vitepress/config.mts |
Makes base environment-configurable and documents the intended versioning flow. |
.github/workflows/docs.yml |
Adds CI jobs for latest build+deploy and tag-triggered snapshot publishing/version list updates. |
- docs.yml: use glob tag pattern v[0-9]*.0.0 (not regex +)
- docs.yml: unify deployment on peaceiris/actions-gh-pages (gh-pages
branch) for both latest and versioned snapshots — removes the
incompatible mix of GitHub Actions Pages deployment and gh-pages branch
- docs.yml: pin actions/checkout to commit SHA (11bd71901bbe…)
- docs.yml: fix versions.json link to /${MAJOR}/ (was /github-code-search/${MAJOR}/)
- config.mts: import versions.json and generate nav version dropdown
dynamically so it stays in sync with CI-prepended entries
| // VITEPRESS_BASE is injected by the snapshot CI job for versioned builds. | ||
| // Falls back to the canonical base for regular deploys. | ||
| base: (process.env.VITEPRESS_BASE ?? "/github-code-search/") as `/${string}/`, |
There was a problem hiding this comment.
base is taken directly from process.env.VITEPRESS_BASE and cast to a template type, but the cast doesn’t ensure the trailing / that VitePress expects for base. If someone sets VITEPRESS_BASE=/github-code-search/v2 (no trailing slash), asset/link generation can break. Consider normalising the env var (ensure it starts/ends with /) before assigning it to base.
| # Deployment strategy: single mechanism — peaceiris/actions-gh-pages (gh-pages branch). | ||
| # • latest docs → pushed to gh-pages root (keep_files: true preserves snapshots) | ||
| # • versioned snapshot → pushed to gh-pages/<major>/ on major release tags | ||
| # GitHub Pages must be configured to serve from the gh-pages branch (not GitHub Actions). | ||
| # |
There was a problem hiding this comment.
PR description says the workflow uses the GitHub Pages “GitHub Actions” deployment flow (upload-pages-artifact + deploy-pages), but this workflow actually publishes via peaceiris/actions-gh-pages to the gh-pages branch and requires Pages to be configured as “Deploy from a branch”. Please align the PR description (and any linked issue acceptance criteria) with the implemented deployment mechanism, or switch the workflow to the Actions-based Pages deployment if that’s the intended approach.
| - name: Build versioned snapshot | ||
| env: | ||
| # config.mts reads VITEPRESS_BASE when set; falls back to /github-code-search/ | ||
| VITEPRESS_BASE: /github-code-search/${{ steps.ver.outputs.major }}/ | ||
| run: bun run docs:build | ||
|
|
There was a problem hiding this comment.
In the snapshot job, the docs are built before versions.json is updated. That means the published snapshot for vX will still render the previous dropdown contents (and won’t list the snapshot’s own version) because config.mts imports docs/public/versions.json at build time. Move the versions.json update step before bun run docs:build (or generate a build-time versions file) so the snapshot’s nav matches the version being published.
| # Idempotent: skip if the entry already exists | ||
| jq --arg text "$MAJOR" --arg link "$LINK" \ | ||
| 'if any(.[]; .link == $link) then . else [{"text": $text, "link": $link}] + . end' \ |
There was a problem hiding this comment.
The jq script prepends a new { text: vX, link: /vX/ } entry but doesn’t update the previous “(latest)” marker. Starting from the current versions.json (v1 (latest)), after tagging v2.0.0 you’ll end up with v2 followed by v1 (latest), which incorrectly labels v1 as latest. Update the script to transfer the “(latest)” suffix (or otherwise mark latest) onto the newly added major version and remove it from the previous one.
| # Idempotent: skip if the entry already exists | |
| jq --arg text "$MAJOR" --arg link "$LINK" \ | |
| 'if any(.[]; .link == $link) then . else [{"text": $text, "link": $link}] + . end' \ | |
| # Idempotent: ensure there is exactly one "(latest)" marker on the current major | |
| jq --arg major "$MAJOR" --arg link "$LINK" \ | |
| ' # First, remove any existing " (latest)" suffix from all entries | |
| (map(.text |= sub(" \\(latest\\)$"; ""))) as $items | |
| | if any($items[]; .link == $link) then | |
| # Entry for this link already exists: update its text to mark it as latest | |
| [ $items[] | if .link == $link | |
| then .text = ($major + " (latest)") | |
| else . | |
| end ] | |
| else | |
| # No entry yet for this major: prepend it and mark as latest | |
| [{"text": ($major + " (latest)"), "link": $link}] + $items | |
| end' \ |
| { text: "v1 (latest)", link: "/" }, | ||
| ...versionsData.map((v: { text: string; link: string }) => ({ | ||
| text: v.text, | ||
| link: v.link, |
There was a problem hiding this comment.
The workflow comment says “VitePress will not add the base a second time”, but VitePress applies base to internal links. When building a snapshot with base=/github-code-search/vX/, dropdown links like /vY/ will typically resolve under the versioned base (e.g. /github-code-search/vX/vY/), breaking cross-version navigation within snapshots. To make the dropdown work from both latest and versioned snapshots, use fully-qualified URLs (or another strategy that bypasses VitePress base rewriting) for version links.
| link: v.link, | |
| // Use fully-qualified URLs for version links so VitePress `base` is not reapplied. | |
| link: v.link.startsWith("http") | |
| ? v.link | |
| : `https://fulll.github.io/github-code-search${v.link}`, |
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)
Motivation
Closes #30. Pre-empts #31.
VitePress doesn't version docs by itself. We need a CI strategy that:
mainbranch as the "latest" docs (/github-code-search/).vX.0.0) and publishes it at/github-code-search/vX/.docs/public/versions.jsonso the nav version dropdown stays in sync.What changed
.github/workflows/docs.yml(new)Three jobs, all triggered by a single workflow:
buildpushtomain(paths:docs/**, the workflow file itself) orworkflow_dispatchbun docs:build→ upload Pages artifactdeploybuildactions/deploy-pages@v4→ publishes to GitHub Pages rootsnapshotpushtag matchingv[0-9]+.0.0VITEPRESS_BASE=/github-code-search/vX/, deploys togh-pagesbranch under/vX/viapeaceiris/actions-gh-pages, prepends entry toversions.jsononmainviastefanzweifel/git-auto-commit-actionAll third-party actions are pinned to commit SHAs.
docs/.vitepress/config.mtsVITEPRESS_BASEis injected by thesnapshotjob. Regular main-branch builds fall back to the canonical base. A comment block explains the full versioning convention.docs/public/versions.json(unchanged)Already initialised with
[{ "text": "v1 (latest)", "link": "/" }]— no change needed.How to verify
On tag push
v2.0.0, thesnapshotjob will:VITEPRESS_BASE=/github-code-search/v2/.vitepress/dist/to thegh-pagesbranch underv2/{ "text": "v2", "link": "/v2/" }prepended toversions.jsononmainThe next
maindeploy will pick up the updatedversions.jsonand the dropdown will showv2.