Skip to content

Comments

docs: versioning strategy — CI snapshot + deploy workflow#39

Merged
shouze merged 2 commits intofeat/vitepress-docsfrom
docs/30-versioning
Feb 23, 2026
Merged

docs: versioning strategy — CI snapshot + deploy workflow#39
shouze merged 2 commits intofeat/vitepress-docsfrom
docs/30-versioning

Conversation

@shouze
Copy link
Contributor

@shouze shouze commented Feb 23, 2026

Motivation

Closes #30. Pre-empts #31.

VitePress doesn't version docs by itself. We need a CI strategy that:

  1. Continuously deploys the main branch as the "latest" docs (/github-code-search/).
  2. Takes a frozen snapshot on each major release tag (vX.0.0) and publishes it at /github-code-search/vX/.
  3. Maintains docs/public/versions.json so the nav version dropdown stays in sync.

What changed

.github/workflows/docs.yml (new)

Three jobs, all triggered by a single workflow:

Job Trigger Action
build push to main (paths: docs/**, the workflow file itself) or workflow_dispatch bun docs:build → upload Pages artifact
deploy Same as build actions/deploy-pages@v4 → publishes to GitHub Pages root
snapshot push tag matching v[0-9]+.0.0 Extracts major version, builds with VITEPRESS_BASE=/github-code-search/vX/, deploys to gh-pages branch under /vX/ via peaceiris/actions-gh-pages, prepends entry to versions.json on main via stefanzweifel/git-auto-commit-action

All third-party actions are pinned to commit SHAs.

docs/.vitepress/config.mts

-  base: "/github-code-search/",
+  base: (process.env.VITEPRESS_BASE ?? "/github-code-search/") as `/${string}/`,

VITEPRESS_BASE is injected by the snapshot job. 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

# Local build (uses fallback base)
bun run docs:build

# Simulated snapshot build
VITEPRESS_BASE=/github-code-search/v2/ bun run docs:build
# → dist should have base set to /github-code-search/v2/

On tag push v2.0.0, the snapshot job will:

  1. Build with VITEPRESS_BASE=/github-code-search/v2/
  2. Push .vitepress/dist/ to the gh-pages branch under v2/
  3. Commit { "text": "v2", "link": "/v2/" } prepended to versions.json on main

The next main deploy will pick up the updated versions.json and the dropdown will show v2.

- .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
Copilot AI review requested due to automatic review settings February 23, 2026 23:09
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 base configurable via VITEPRESS_BASE for 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
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.

Comment on lines +19 to +21
// 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}/`,
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +22
# 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).
#
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +105 to +110
- 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

Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +126 to +128
# 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' \
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
# 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' \

Copilot uses AI. Check for mistakes.
{ text: "v1 (latest)", link: "/" },
...versionsData.map((v: { text: string; link: string }) => ({
text: v.text,
link: v.link,
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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}`,

Copilot uses AI. Check for mistakes.
@shouze shouze merged commit 989a679 into feat/vitepress-docs Feb 23, 2026
6 checks passed
@shouze shouze deleted the docs/30-versioning branch February 23, 2026 23:25
shouze added a commit that referenced this pull request Feb 23, 2026
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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant