1+ # =============================================================================
2+ # CI/CD Workflow: OpenSIN Documentation Build & Deploy
3+ # =============================================================================
4+ # This workflow builds the VitePress documentation site using bun (not npm!)
5+ # and deploys to Cloudflare Pages on the main branch.
6+ #
7+ # BUN-ONLY MANDATE (AGENTS.md): npm is permanently banned.
8+ # Global Brain hooks (PRIORITY -100.0) sync before/after every run.
9+ #
10+ # Secrets required (set in GitHub repo settings):
11+ # - CLOUDFLARE_API_TOKEN: Cloudflare Pages API token
12+ # - CLOUDFLARE_ACCOUNT_ID: Cloudflare account ID
13+ # =============================================================================
14+
15+ name : Docs Build & Deploy
16+
17+ on :
18+ push :
19+ branches : [main, fix/docs-modernize-standards]
20+ pull_request :
21+ branches : [main]
22+
23+ # =============================================================================
24+ # Environment variables — Bun version pinned for reproducibility
25+ # =============================================================================
26+ env :
27+ BUN_VERSION : " 1.3.12"
28+ NODE_VERSION : " 22"
29+
30+ # =============================================================================
31+ # Job definitions
32+ # =============================================================================
33+ jobs :
34+ # ---------------------------------------------------------------------------
35+ # Job: build
36+ # Purpose: Install dependencies with bun, run VitePress build, verify output
37+ # ---------------------------------------------------------------------------
38+ build :
39+ name : VitePress Build (bun)
40+ runs-on : ubuntu-latest
41+ timeout-minutes : 15
42+
43+ steps :
44+ # -----------------------------------------------------------------------
45+ # STEP 1: Global Brain sync BEFORE run (PRIORITY -100.0 mandate)
46+ # Loads active context from the persistent brain before each OpenCode run
47+ # -----------------------------------------------------------------------
48+ - name : Global Brain sync before run
49+ run : |
50+ echo "=== PCPM Before-Run Hook ==="
51+ node /Users/jeremy/dev/global-brain/src/cli.js orchestrate \
52+ --project opensin-docs \
53+ --project-root "$PWD" \
54+ 2>/dev/null || \
55+ echo "Global Brain sync completed (or skipped)"
56+
57+ # -----------------------------------------------------------------------
58+ # STEP 2: Checkout with full history for proper submodule handling
59+ # -----------------------------------------------------------------------
60+ - name : Checkout
61+ uses : actions/checkout@v4
62+ with :
63+ submodules : true
64+ fetch-depth : 0
65+
66+ # -----------------------------------------------------------------------
67+ # STEP 3: Install Bun (required — npm permanently banned per AGENTS.md)
68+ # -----------------------------------------------------------------------
69+ - name : Install Bun
70+ uses : oven-sh/setup-bun@v3
71+ with :
72+ bun-version : " ${{ env.BUN_VERSION }}"
73+
74+ # -----------------------------------------------------------------------
75+ # STEP 4: Install dependencies ONLY using bun (AGENTS.md CI/CD mandate)
76+ # Bun is ~90% faster and uses 10x less RAM than npm
77+ # -----------------------------------------------------------------------
78+ - name : Install dependencies (bun ONLY — npm banned per AGENTS.md)
79+ run : bun install
80+
81+ # -----------------------------------------------------------------------
82+ # STEP 5: Lint check — verify NO npm patterns in source code
83+ # This ensures the BUN-ONLY mandate is enforced across all source files
84+ # -----------------------------------------------------------------------
85+ - name : Lint check (no npm patterns)
86+ run : |
87+ echo "=== BUN-ONLY Verification ==="
88+ # Search for npm patterns that should NOT exist
89+ NPM_PATTERNS=$(grep -r "npm install\|npm run\|package-lock\|npx " . \
90+ --include="*.md" \
91+ --include="*.json" \
92+ --include="*.yml" \
93+ --include="*.yaml" \
94+ --include="*.sh" \
95+ ! -path "./node_modules/*" \
96+ ! -path "./.vitepress/dist/*" \
97+ ! -path "./.git/*" \
98+ 2>/dev/null | grep -v "node_modules" || true)
99+
100+ if [ -n "$NPM_PATTERNS" ]; then
101+ echo "FAIL: Found npm patterns:"
102+ echo "$NPM_PATTERNS"
103+ exit 1
104+ else
105+ echo "PASS: No npm patterns found — BUN-ONLY verified"
106+ fi
107+
108+ # -----------------------------------------------------------------------
109+ # STEP 6: Build VitePress documentation site
110+ # Uses bun run docs:build (NOT npm run docs:build)
111+ # -----------------------------------------------------------------------
112+ - name : Build docs
113+ run : |
114+ echo "=== VitePress Build ==="
115+ bun run docs:build
116+
117+ # -----------------------------------------------------------------------
118+ # STEP 7: Verify build output exists
119+ # VitePress outputs to .vitepress/dist/ — this must exist for deploy
120+ # -----------------------------------------------------------------------
121+ - name : Verify build output exists
122+ run : |
123+ echo "=== Build Verification ==="
124+ if [ -d ".vitepress/dist" ] && [ -f ".vitepress/dist/index.html" ]; then
125+ echo "PASS: Build output verified"
126+ echo " Dist size: $(du -sh .vitepress/dist | cut -f1)"
127+ echo " Files: $(find .vitepress/dist -type f | wc -l)"
128+ else
129+ echo "FAIL: Build output missing or incomplete"
130+ echo " .vitepress/dist exists: $(test -d .vitepress/dist && echo YES || echo NO)"
131+ ls -la .vitepress/ 2>/dev/null || echo "No .vitepress dir"
132+ exit 1
133+ fi
134+
135+ # -----------------------------------------------------------------------
136+ # STEP 8: Global Brain sync AFTER successful build (PRIORITY -100.0)
137+ # Extracts knowledge from the completed session back into the brain
138+ # -----------------------------------------------------------------------
139+ - name : Global Brain sync after run
140+ if : success()
141+ run : |
142+ echo "=== PCPM After-Run Hook ==="
143+ node /Users/jeremy/dev/global-brain/src/cli.js extract-knowledge \
144+ --project opensin-docs \
145+ --project-root "$PWD" \
146+ 2>/dev/null || \
147+ echo "Post-run knowledge extraction completed (or skipped)"
148+
149+ # -----------------------------------------------------------------------
150+ # STEP 9: Upload build artifacts for deploy job
151+ # Artifacts are needed because build and deploy are separate jobs
152+ # -----------------------------------------------------------------------
153+ - name : Upload build artifacts
154+ if : github.ref == 'refs/heads/main'
155+ uses : actions/upload-pages-artifact@v3
156+ with :
157+ path : .vitepress/dist
158+
159+ # ---------------------------------------------------------------------------
160+ # Job: deploy
161+ # Purpose: Deploy built docs to Cloudflare Pages (main branch only)
162+ # ---------------------------------------------------------------------------
163+ deploy :
164+ name : Cloudflare Pages Deploy
165+ if : github.ref == 'refs/heads/main'
166+ needs : build
167+ runs-on : ubuntu-latest
168+ timeout-minutes : 10
169+ permissions :
170+ contents : read
171+ deployments : write
172+
173+ steps :
174+ # -----------------------------------------------------------------------
175+ # STEP 1: Download build artifacts from the build job
176+ # -----------------------------------------------------------------------
177+ - name : Download built artifacts
178+ uses : actions/download-artifact@v4
179+ with :
180+ name : github-pages
181+ path : .vitepress/dist
182+
183+ # -----------------------------------------------------------------------
184+ # STEP 2: Deploy to Cloudflare Pages
185+ # Uses wrangler for deployment (bun run deploy, NOT npm run deploy)
186+ # -----------------------------------------------------------------------
187+ - name : Deploy to Cloudflare Pages
188+ uses : cloudflare/pages-action@v1
189+ with :
190+ apiToken : ${{ secrets.CLOUDFLARE_API_TOKEN }}
191+ accountId : ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
192+ projectName : opensin-docs
193+ directory : .vitepress/dist
194+ gitHubToken : ${{ secrets.GITHUB_TOKEN }}
0 commit comments