Skip to content

Commit 41c85f3

Browse files
committed
🚀 Add GitHub Pages deployment with playground support
Introduce a complete CI/CD pipeline for deploying docs and the playground app to GitHub Pages as a unified site. The changes include: - New Vite config for building the playground as a static SPA with correct base path for the /playground/ subdirectory - Script to combine VitePress docs and playground builds into dist-pages/ - Updated CI workflow that builds docs and playground separately, combines them, and deploys to GitHub Pages on main branch pushes - New npm scripts: playground:build, playground:preview, and pages:build - Nav link to playground added in docs navigation The workflow also switches from npm to pnpm, adds workflow concurrency, and reorganizes jobs for cleaner separation of build, pages, and release.
1 parent 47e3dce commit 41c85f3

File tree

6 files changed

+213
-70
lines changed

6 files changed

+213
-70
lines changed

.github/workflows/ci-cd.yml

Lines changed: 92 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,135 @@
1-
name: LightScript Workshop
1+
name: LightScript Workshop
22

33
on:
44
push:
5-
branches:
6-
- main
7-
tags:
8-
- "v*.*.*"
5+
branches: [main]
6+
tags: ["v*.*.*"]
97
pull_request:
10-
branches:
11-
- main
8+
branches: [main]
9+
workflow_dispatch:
1210

13-
env:
14-
NODE_VERSION: "20" # Current LTS version
15-
ARTIFACT_NAME: lightscript-effects
16-
ARTIFACT_PATH: ./dist/
11+
concurrency:
12+
group: ${{ github.workflow }}-${{ github.ref }}
13+
cancel-in-progress: true
14+
15+
permissions:
16+
contents: write
17+
pages: write
18+
id-token: write
1719

1820
jobs:
19-
build_and_test:
20-
name: 🔨 Build + Test
21+
build:
22+
name: Build & Test
2123
runs-on: ubuntu-latest
2224
steps:
23-
- name: 📥 Checkout code
25+
- name: Checkout
2426
uses: actions/checkout@v4
2527

26-
- name: 🔧 Setup Node.js ${{ env.NODE_VERSION }}
28+
- name: ⚙ Setup pnpm
29+
uses: pnpm/action-setup@v4
30+
31+
- name: ⚙ Setup Node.js
2732
uses: actions/setup-node@v4
2833
with:
29-
node-version: ${{ env.NODE_VERSION }}
30-
cache: "npm"
31-
cache-dependency-path: "**/package-lock.json"
34+
node-version: 20
35+
cache: pnpm
3236

33-
- name: 📦 Install dependencies
34-
run: npm ci --prefer-offline --no-audit
37+
- name: Install dependencies
38+
run: pnpm install --frozen-lockfile
3539

36-
- name: 📊 Cache build artifacts
37-
uses: actions/cache@v4
38-
with:
39-
path: |
40-
dist/
41-
.vite/
42-
key: ${{ runner.os }}-build-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('src/**/*') }}
43-
restore-keys: |
44-
${{ runner.os }}-build-${{ hashFiles('**/package-lock.json') }}-
45-
${{ runner.os }}-build-
40+
- name: ✓ Lint
41+
run: pnpm lint
4642

47-
- name: 🧹 Run linter
48-
run: npm run lint
43+
- name: ✓ Typecheck
44+
run: pnpm typecheck
4945

50-
- name: 🧪 Run tests
51-
run: npm test
46+
- name: ✓ Test
47+
run: pnpm test
5248

53-
- name: 🏗️ Build project
54-
run: npm run build
49+
- name: Build packages
50+
run: pnpm build:packages
5551

56-
- name: 📊 Analyze bundle sizes
57-
run: npm run bundle:size
58-
continue-on-error: true
52+
- name: ⬡ Build effects
53+
run: pnpm build:effects
5954

60-
- name: 📤 Upload build artifacts
55+
- name: Upload effects
6156
uses: actions/upload-artifact@v4
6257
with:
63-
name: ${{ env.ARTIFACT_NAME }}
64-
path: ${{ env.ARTIFACT_PATH }}
65-
retention-days: 7 # Keep artifacts for 7 days
58+
name: lightscript-effects
59+
path: dist/
60+
retention-days: 7
6661

67-
analyze:
68-
name: 🔍 Analyze Project
62+
pages:
63+
name: ▸ Build Pages
6964
runs-on: ubuntu-latest
65+
needs: build
66+
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
7067
steps:
71-
- name: 📥 Checkout code
68+
- name: Checkout
7269
uses: actions/checkout@v4
7370

74-
- name: 🔧 Setup Node.js ${{ env.NODE_VERSION }}
71+
- name: ⚙ Setup pnpm
72+
uses: pnpm/action-setup@v4
73+
74+
- name: ⚙ Setup Node.js
7575
uses: actions/setup-node@v4
7676
with:
77-
node-version: ${{ env.NODE_VERSION }}
78-
cache: "npm"
79-
cache-dependency-path: "**/package-lock.json"
77+
node-version: 20
78+
cache: pnpm
79+
80+
- name: ↓ Install dependencies
81+
run: pnpm install --frozen-lockfile
82+
83+
- name: ⬡ Build packages
84+
run: pnpm build:packages
85+
86+
- name: ⬡ Build docs
87+
run: pnpm docs:build
8088

81-
- name: 📦 Install dependencies
82-
run: npm ci
89+
- name: ⬡ Build playground
90+
run: pnpm playground:build
8391

84-
- name: 🧹 Run ESLint
85-
run: npm run lint
86-
continue-on-error: true
92+
- name: ◇ Combine builds
93+
run: node scripts/combine-pages.js
8794

88-
- name: 🔎 TypeScript type check
89-
run: npx tsc --noEmit
90-
continue-on-error: true
95+
- name: ↑ Upload Pages artifact
96+
uses: actions/upload-pages-artifact@v3
97+
with:
98+
path: dist-pages
99+
100+
deploy:
101+
name: → Deploy Pages
102+
runs-on: ubuntu-latest
103+
needs: pages
104+
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
105+
environment:
106+
name: github-pages
107+
url: ${{ steps.deployment.outputs.page_url }}
108+
steps:
109+
- name: ⟶ Deploy to GitHub Pages
110+
id: deployment
111+
uses: actions/deploy-pages@v4
91112

92113
release:
93-
name: 🚀 Release
94-
if: startsWith(github.ref, 'refs/tags/')
95-
needs: build_and_test
96-
permissions:
97-
contents: write
114+
name: ★ Release
98115
runs-on: ubuntu-latest
116+
needs: build
117+
if: startsWith(github.ref, 'refs/tags/')
99118
steps:
100-
- name: 📥 Download build artifact
119+
- name: Download effects
101120
uses: actions/download-artifact@v4
102121
with:
103-
name: ${{ env.ARTIFACT_NAME }}
122+
name: lightscript-effects
123+
path: dist/
124+
125+
- name: ◇ Create archive
126+
run: |
127+
cd dist
128+
zip -r ../lightscript-effects.zip .
104129
105-
- name: 🎉 Create GitHub Release
130+
- name: Create GitHub Release
106131
uses: softprops/action-gh-release@v2
107132
with:
108-
files: ${{ env.ARTIFACT_NAME }}
133+
files: lightscript-effects.zip
109134
name: Release ${{ github.ref_name }}
110-
draft: false
111-
prerelease: false
112135
generate_release_notes: true

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ lerna-debug.log*
1010
node_modules
1111
dist
1212
dist-ssr
13+
dist-playground
14+
dist-pages
1315
*.local
1416

1517
# Editor directories and files

docs/.vitepress/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export default defineConfig({
3434
{ link: '/reference/', text: 'Reference' },
3535
{ link: '/examples/', text: 'Examples' },
3636
{ link: '/ai/', text: 'AI' },
37+
{ link: '/playground/', text: 'Playground' },
3738
],
3839

3940
search: {

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@
3939
"dev:fast": "vite --host 0.0.0.0 --port 4096",
4040
"docs": "pnpm --filter lightscript-workshop-docs dev",
4141
"docs:build": "pnpm --filter lightscript-workshop-docs build",
42-
"docs:preview": "pnpm --filter lightscript-workshop-docs preview"
42+
"docs:preview": "pnpm --filter lightscript-workshop-docs preview",
43+
"playground:build": "vite build --config vite.config.playground.ts",
44+
"playground:preview": "vite preview --config vite.config.playground.ts",
45+
"pages:build": "pnpm docs:build && pnpm playground:build && node scripts/combine-pages.js"
4346
},
4447
"keywords": [
4548
"webgl",

scripts/combine-pages.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* Combines VitePress docs and Playground builds for GitHub Pages deployment
5+
*
6+
* Output structure:
7+
* dist-pages/
8+
* ├── index.html (docs home)
9+
* ├── getting-started/
10+
* ├── reference/
11+
* ├── playground/ (the app)
12+
* │ ├── index.html
13+
* │ └── assets/
14+
* └── ...
15+
*/
16+
17+
import { cpSync, existsSync, mkdirSync, rmSync } from 'node:fs'
18+
import { resolve } from 'node:path'
19+
20+
const ROOT = resolve(import.meta.dirname, '..')
21+
const DOCS_DIST = resolve(ROOT, 'docs/.vitepress/dist')
22+
const PLAYGROUND_DIST = resolve(ROOT, 'dist-playground')
23+
const OUTPUT = resolve(ROOT, 'dist-pages')
24+
25+
console.log('\n✨ Combining docs + playground for GitHub Pages\n')
26+
27+
// Validate source directories exist
28+
if (!existsSync(DOCS_DIST)) {
29+
console.error('❌ Docs build not found. Run `pnpm docs:build` first.')
30+
process.exit(1)
31+
}
32+
33+
if (!existsSync(PLAYGROUND_DIST)) {
34+
console.error('❌ Playground build not found. Run `pnpm playground:build` first.')
35+
process.exit(1)
36+
}
37+
38+
// Clean output directory
39+
if (existsSync(OUTPUT)) {
40+
console.log('🧹 Cleaning existing dist-pages...')
41+
rmSync(OUTPUT, { recursive: true })
42+
}
43+
44+
mkdirSync(OUTPUT, { recursive: true })
45+
46+
// Copy docs (the main site)
47+
console.log('📚 Copying docs...')
48+
cpSync(DOCS_DIST, OUTPUT, { recursive: true })
49+
50+
// Copy playground into subdirectory
51+
console.log('🎮 Copying playground...')
52+
const playgroundOutput = resolve(OUTPUT, 'playground')
53+
mkdirSync(playgroundOutput, { recursive: true })
54+
cpSync(PLAYGROUND_DIST, playgroundOutput, { recursive: true })
55+
56+
console.log('\n✅ Combined build complete!')
57+
console.log(` Output: ${OUTPUT}\n`)
58+
console.log('📁 Structure:')
59+
console.log(' dist-pages/')
60+
console.log(' ├── index.html (docs)')
61+
console.log(' ├── getting-started/')
62+
console.log(' ├── reference/')
63+
console.log(' ├── playground/')
64+
console.log(' │ └── index.html (app)')
65+
console.log(' └── ...\n')

vite.config.playground.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { resolve } from 'node:path'
2+
import swcPlugin from '@vitejs/plugin-react-swc'
3+
import { defineConfig } from 'vite'
4+
import glsl from 'vite-plugin-glsl'
5+
6+
import { lightscriptDecoratorsPlugin } from './plugins'
7+
8+
/**
9+
* Vite config for building the playground as a static SPA
10+
* This builds the dev UI for deployment to GitHub Pages
11+
*/
12+
export default defineConfig({
13+
base: '/lightscript-workshop/playground/',
14+
15+
build: {
16+
emptyOutDir: true,
17+
outDir: 'dist-playground',
18+
rollupOptions: {
19+
input: resolve(__dirname, 'index.html'),
20+
},
21+
},
22+
23+
define: {
24+
__DEV__: false,
25+
__EFFECT_ID__: JSON.stringify('default'),
26+
},
27+
28+
plugins: [
29+
// React SWC with Preact compatibility
30+
swcPlugin({
31+
tsDecorators: true,
32+
}),
33+
34+
// GLSL shader support
35+
glsl(),
36+
37+
// Decorator metadata for controls
38+
lightscriptDecoratorsPlugin(),
39+
],
40+
41+
resolve: {
42+
alias: {
43+
'@lightscript/core': resolve(__dirname, 'packages/core/src'),
44+
'@lightscript/dev': resolve(__dirname, 'packages/dev/src'),
45+
react: 'preact/compat',
46+
'react-dom': 'preact/compat',
47+
},
48+
},
49+
})

0 commit comments

Comments
 (0)