Skip to content

Commit af58430

Browse files
authored
Merge branch 'main' into small-docs-patch
2 parents 22c09df + b8ab58f commit af58430

11 files changed

Lines changed: 583 additions & 80 deletions

File tree

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
name: 'Build and deploy docs'
2+
description: >-
3+
Build the VitePress docs site (which bundles install.sh / install.ps1 into
4+
its public assets) and deploy it to a void.app project. Run on a Linux
5+
runner after checkout. See rfcs/deploy-docs-on-release.md for which
6+
workflow deploys to which project.
7+
8+
inputs:
9+
void-project:
10+
description: 'void.app project to deploy to (e.g. viteplus, viteplus-main).'
11+
required: true
12+
void-token:
13+
description: 'void.app deploy token (pass secrets.VOID_TOKEN).'
14+
required: true
15+
cache-ref:
16+
description: >-
17+
Ref-scoped segment of the Vite Task cache key: main, or pr-<number> for
18+
PR previews. Non-main refs fall back to the main cache on restore.
19+
required: false
20+
default: 'main'
21+
cache-sha:
22+
description: 'Commit sha that scopes the primary cache key.'
23+
required: false
24+
default: ${{ github.sha }}
25+
site-origin:
26+
description: >-
27+
Origin of this deploy when it is not production viteplus.dev
28+
(e.g. https://main.viteplus.dev). When set, the docs build rewrites the
29+
https://vite.plus installer URLs to this origin's install scripts.
30+
Leave empty for production.
31+
required: false
32+
default: ''
33+
34+
runs:
35+
using: 'composite'
36+
steps:
37+
- uses: voidzero-dev/setup-vp@250f29ce396baf5e8f24498e17c0dfdebabc26eb # main
38+
with:
39+
cache: true
40+
working-directory: docs
41+
cache-dependency-path: docs/pnpm-lock.yaml
42+
43+
- name: Compute Vite Task cache keys
44+
id: cache-keys
45+
shell: bash
46+
env:
47+
CACHE_REF: ${{ inputs.cache-ref }}
48+
CACHE_SHA: ${{ inputs.cache-sha }}
49+
run: |
50+
prefix="vite-task-docs-${RUNNER_OS}-${RUNNER_ARCH}"
51+
{
52+
echo "key=${prefix}-${CACHE_REF}-${CACHE_SHA}"
53+
echo 'restore-keys<<EOF'
54+
echo "${prefix}-${CACHE_REF}-"
55+
if [ "$CACHE_REF" != 'main' ]; then
56+
echo "${prefix}-main-"
57+
fi
58+
echo 'EOF'
59+
} >> "$GITHUB_OUTPUT"
60+
61+
- name: Restore docs Vite Task cache
62+
id: vite-task-cache
63+
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
64+
with:
65+
path: docs/node_modules/.vite/task-cache
66+
key: ${{ steps.cache-keys.outputs.key }}
67+
# Prefer this ref's newest cache; Vite Task fingerprints decide reuse.
68+
restore-keys: ${{ steps.cache-keys.outputs.restore-keys }}
69+
70+
- run: vp run build
71+
shell: bash
72+
working-directory: docs
73+
env:
74+
DOCS_SITE_ORIGIN: ${{ inputs.site-origin }}
75+
76+
- name: Save docs Vite Task cache
77+
if: success() && steps.vite-task-cache.outputs.cache-hit != 'true'
78+
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
79+
with:
80+
path: docs/node_modules/.vite/task-cache
81+
key: ${{ steps.vite-task-cache.outputs.cache-primary-key }}
82+
83+
- run: vpx void deploy --dir docs/.vitepress/dist
84+
shell: bash
85+
env:
86+
VOID_PROJECT: ${{ inputs.void-project }}
87+
VOID_TOKEN: ${{ inputs.void-token }}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: Deploy Docs Main Preview
2+
3+
permissions: {}
4+
5+
# Deploys the docs at the head of main to main.viteplus.dev (the viteplus-main
6+
# void.app project) so developers can preview unreleased docs. Production
7+
# viteplus.dev deploys from release.yml instead.
8+
# See rfcs/deploy-docs-on-release.md.
9+
on:
10+
push:
11+
branches: [main]
12+
paths:
13+
- 'docs/**'
14+
- 'packages/cli/install.sh'
15+
- 'packages/cli/install.ps1'
16+
- '.github/workflows/deploy-docs-main.yml'
17+
- '.github/actions/deploy-docs/**'
18+
19+
concurrency:
20+
group: deploy-docs-main
21+
cancel-in-progress: true
22+
23+
defaults:
24+
run:
25+
shell: bash
26+
27+
jobs:
28+
deploy:
29+
if: github.repository == 'voidzero-dev/vite-plus'
30+
runs-on: ubuntu-latest
31+
permissions:
32+
contents: read
33+
steps:
34+
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
35+
36+
- uses: ./.github/actions/deploy-docs
37+
with:
38+
void-project: viteplus-main
39+
void-token: ${{ secrets.VOID_TOKEN }}
40+
site-origin: https://main.viteplus.dev

.github/workflows/deploy-docs-preview.yml

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ on:
99
- 'packages/cli/install.sh'
1010
- 'packages/cli/install.ps1'
1111
- '.github/workflows/deploy-docs-preview.yml'
12+
- '.github/actions/deploy-docs/**'
1213

1314
concurrency:
1415
group: deploy-docs-preview-${{ github.event.pull_request.number }}
@@ -28,41 +29,17 @@ jobs:
2829
contents: read
2930
pull-requests: write
3031
env:
31-
VOID_PROJECT: viteplus-staging
3232
PREVIEW_URL: https://viteplus-staging.void.app/
3333
steps:
3434
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
3535

36-
- uses: voidzero-dev/setup-vp@250f29ce396baf5e8f24498e17c0dfdebabc26eb # main
36+
- uses: ./.github/actions/deploy-docs
3737
with:
38-
cache: true
39-
working-directory: docs
40-
cache-dependency-path: docs/pnpm-lock.yaml
41-
42-
- name: Restore docs Vite Task cache
43-
id: vite-task-cache
44-
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
45-
with:
46-
path: docs/node_modules/.vite/task-cache
47-
key: vite-task-docs-${{ runner.os }}-${{ runner.arch }}-pr-${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }}
48-
# Prefer this PR's newest cache, then fall back to main for new PRs.
49-
restore-keys: |
50-
vite-task-docs-${{ runner.os }}-${{ runner.arch }}-pr-${{ github.event.pull_request.number }}-
51-
vite-task-docs-${{ runner.os }}-${{ runner.arch }}-main-
52-
53-
- run: vp run build
54-
working-directory: docs
55-
56-
- name: Save docs Vite Task cache
57-
if: success() && steps.vite-task-cache.outputs.cache-hit != 'true'
58-
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
59-
with:
60-
path: docs/node_modules/.vite/task-cache
61-
key: ${{ steps.vite-task-cache.outputs.cache-primary-key }}
62-
63-
- run: vpx void deploy --dir docs/.vitepress/dist
64-
env:
65-
VOID_TOKEN: ${{ secrets.VOID_TOKEN }}
38+
void-project: viteplus-staging
39+
void-token: ${{ secrets.VOID_TOKEN }}
40+
cache-ref: pr-${{ github.event.pull_request.number }}
41+
cache-sha: ${{ github.event.pull_request.head.sha }}
42+
site-origin: https://viteplus-staging.void.app
6643

6744
- name: Comment on PR
6845
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9

.github/workflows/deploy-docs.yml

Lines changed: 12 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@ name: Deploy Docs
22

33
permissions: {}
44

5+
# Deploys production viteplus.dev, which also serves install.sh / install.ps1
6+
# behind https://vite.plus. Runs from release.yml after a stable release is
7+
# published, or manually here for urgent updates. Pushes to main deploy to
8+
# main.viteplus.dev via deploy-docs-main.yml instead.
9+
# See rfcs/deploy-docs-on-release.md.
510
on:
6-
push:
7-
branches: [main]
8-
paths:
9-
- 'docs/**'
10-
- 'packages/cli/install.sh'
11-
- 'packages/cli/install.ps1'
12-
- '.github/workflows/deploy-docs.yml'
1311
workflow_dispatch:
1412

13+
# Shared with the deploy-docs job in release.yml so production deploys
14+
# serialize across both entry paths. GitHub keeps only the newest pending run
15+
# in the group (a queued deploy replaces a pending one), so production
16+
# converges to the newest queued content; the running deploy always completes.
1517
concurrency:
1618
group: deploy-docs
1719
cancel-in-progress: false
@@ -26,37 +28,10 @@ jobs:
2628
runs-on: ubuntu-latest
2729
permissions:
2830
contents: read
29-
env:
30-
VOID_PROJECT: viteplus
3131
steps:
3232
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
3333

34-
- uses: voidzero-dev/setup-vp@250f29ce396baf5e8f24498e17c0dfdebabc26eb # main
34+
- uses: ./.github/actions/deploy-docs
3535
with:
36-
cache: true
37-
working-directory: docs
38-
cache-dependency-path: docs/pnpm-lock.yaml
39-
40-
- name: Restore docs Vite Task cache
41-
id: vite-task-cache
42-
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
43-
with:
44-
path: docs/node_modules/.vite/task-cache
45-
key: vite-task-docs-${{ runner.os }}-${{ runner.arch }}-main-${{ github.sha }}
46-
# Restore the latest main cache; Vite Task fingerprints decide reuse.
47-
restore-keys: |
48-
vite-task-docs-${{ runner.os }}-${{ runner.arch }}-main-
49-
50-
- run: vp run build
51-
working-directory: docs
52-
53-
- name: Save docs Vite Task cache
54-
if: success() && steps.vite-task-cache.outputs.cache-hit != 'true'
55-
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
56-
with:
57-
path: docs/node_modules/.vite/task-cache
58-
key: ${{ steps.vite-task-cache.outputs.cache-primary-key }}
59-
60-
- run: vpx void deploy --dir docs/.vitepress/dist
61-
env:
62-
VOID_TOKEN: ${{ secrets.VOID_TOKEN }}
36+
void-project: viteplus
37+
void-token: ${{ secrets.VOID_TOKEN }}

.github/workflows/release.yml

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,34 @@ jobs:
213213
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
214214
run: gh release edit "v${VERSION}" --draft=false --repo "${{ github.repository }}"
215215

216+
# Deploy viteplus.dev from the release commit after the npm packages and the
217+
# GitHub release are published, so the site and the install scripts always
218+
# match the released vp. Skipped for prereleases: production docs must keep
219+
# describing the latest stable release. See rfcs/deploy-docs-on-release.md.
220+
deploy-docs:
221+
name: Deploy docs
222+
runs-on: ubuntu-latest
223+
needs: [check, Release]
224+
if: >-
225+
needs.check.outputs.version_changed == 'true' &&
226+
!contains(needs.check.outputs.version, '-')
227+
# Shared with deploy-docs.yml so production deploys serialize across both
228+
# entry paths. Only the newest pending run survives in the group; if this
229+
# job's pending run is replaced by a manual dispatch, the canceled job
230+
# holds back discord-notify and the deploy must be re-run.
231+
concurrency:
232+
group: deploy-docs
233+
cancel-in-progress: false
234+
permissions:
235+
contents: read
236+
steps:
237+
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
238+
239+
- uses: ./.github/actions/deploy-docs
240+
with:
241+
void-project: viteplus
242+
void-token: ${{ secrets.VOID_TOKEN }}
243+
216244
# Build and push the official toolchain Docker image to GHCR after the npm
217245
# release is published (the image installs vp from npm, so the version must
218246
# exist first). See docker/Dockerfile and docs/guide/docker.md.
@@ -266,15 +294,22 @@ jobs:
266294
VP_VERSION=${{ env.VERSION }}
267295
provenance: false
268296

269-
# Announce the release on Discord last, after the Docker images are published,
270-
# so the message can include the GHCR image. Runs after the npm release
271-
# (Release) and the images (publish-docker).
297+
# Announce the release on Discord last, after the Docker images and the docs
298+
# are published, so the message never points at a missing image or a site
299+
# that still shows the previous release.
272300
discord-notify:
273301
name: Notify Discord
274302
runs-on: ubuntu-latest
275303
# publish-docker already needs Release, so depending on it orders this last.
276-
needs: [check, publish-docker]
277-
if: needs.check.outputs.version_changed == 'true'
304+
# deploy-docs is skipped for prereleases; gate on its result explicitly so
305+
# prerelease announcements still go out, while a failed docs deploy on a
306+
# stable release holds the announcement back.
307+
needs: [check, publish-docker, deploy-docs]
308+
if: >-
309+
!cancelled() &&
310+
needs.check.outputs.version_changed == 'true' &&
311+
needs.publish-docker.result == 'success' &&
312+
(needs.deploy-docs.result == 'success' || needs.deploy-docs.result == 'skipped')
278313
env:
279314
VERSION: ${{ needs.check.outputs.version }}
280315
IMAGE: ghcr.io/voidzero-dev/vite-plus

docs/.vitepress/config.mts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,26 @@ import { groupIconMdPlugin, groupIconVitePlugin } from 'vitepress-plugin-group-i
77
import llmstxt from 'vitepress-plugin-llms';
88
import { withMermaid } from 'vitepress-plugin-mermaid';
99

10+
// Non-production deploys (the main preview, PR staging) serve their own
11+
// copies of the install scripts and llms dumps, so the https://vite.plus
12+
// installer shortcuts and absolute site URLs must point at the deploy's
13+
// origin instead of production. The deploy workflows set DOCS_SITE_ORIGIN via
14+
// the deploy-docs composite action; markdown content is rewritten through
15+
// markdown-it below, and Vue components read the __DOCS_*__ define constants.
16+
const siteOrigin = process.env.DOCS_SITE_ORIGIN;
17+
const docsOrigin = siteOrigin || 'https://viteplus.dev';
18+
const installShUrl = siteOrigin ? `${siteOrigin}/install.sh` : 'https://vite.plus';
19+
const installPs1Url = siteOrigin ? `${siteOrigin}/install.ps1` : 'https://vite.plus/ps1';
20+
21+
function rewriteInstallUrls(text: string): string {
22+
if (!siteOrigin) {
23+
return text;
24+
}
25+
return text
26+
.replaceAll('https://vite.plus/ps1', installPs1Url)
27+
.replaceAll('https://vite.plus', installShUrl);
28+
}
29+
1030
const taskRunnerGuideItems = [
1131
{
1232
text: 'Run',
@@ -113,6 +133,11 @@ export default extendConfig(
113133
['meta', { name: 'twitter:site', content: '@voidzerodev' }],
114134
],
115135
vite: {
136+
define: {
137+
__DOCS_ORIGIN__: JSON.stringify(docsOrigin),
138+
__DOCS_INSTALL_SH_URL__: JSON.stringify(installShUrl),
139+
__DOCS_INSTALL_PS1_URL__: JSON.stringify(installPs1Url),
140+
},
116141
optimizeDeps: {
117142
include: ['mermaid > @braintree/sanitize-url'],
118143
},
@@ -258,6 +283,31 @@ export default extendConfig(
258283
markdown: {
259284
config(md) {
260285
md.use(groupIconMdPlugin);
286+
if (siteOrigin) {
287+
md.core.ruler.push('rewrite-install-urls', (state) => {
288+
const walk = (tokens: typeof state.tokens) => {
289+
for (const token of tokens) {
290+
if (
291+
token.type === 'fence' ||
292+
token.type === 'code_inline' ||
293+
token.type === 'text'
294+
) {
295+
token.content = rewriteInstallUrls(token.content);
296+
}
297+
if (token.type === 'link_open') {
298+
const href = token.attrGet('href');
299+
if (href) {
300+
token.attrSet('href', rewriteInstallUrls(href));
301+
}
302+
}
303+
if (token.children) {
304+
walk(token.children);
305+
}
306+
}
307+
};
308+
walk(state.tokens);
309+
});
310+
}
261311
},
262312
},
263313
}),

docs/.vitepress/env.d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
// Build-time constants injected via vite.define in config.mts. They point at
2+
// the current deploy's origin (production, main preview, or PR staging). The
3+
// dunder names follow the Vite convention for compile-time replaced globals.
4+
// oxlint-disable-next-line no-underscore-dangle
5+
declare const __DOCS_ORIGIN__: string;
6+
// oxlint-disable-next-line no-underscore-dangle
7+
declare const __DOCS_INSTALL_SH_URL__: string;
8+
// oxlint-disable-next-line no-underscore-dangle
9+
declare const __DOCS_INSTALL_PS1_URL__: string;
10+
111
// Vue SFC module declaration
212
declare module '*.vue' {
313
import type { DefineComponent } from 'vue';

0 commit comments

Comments
 (0)