cloudflare/kumo

Public

mirrored from https://github.com/cloudflare/kumoAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
2ae9d85fb235eccab150eb2ae471e6165382e26d

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

.github/workflows/preview.yml

268lines · modecode

1name: Preview
2
3on:
4 pull_request:
5 # Also trigger on push to PR branches (for bots that push via API)
6 push:
7 branches:
8 - "opencode/**"
9 - "changeset-release/main"
10
11permissions:
12 contents: write
13 pull-requests: write
14
15concurrency:
16 group: preview-${{ github.event.pull_request.number || github.ref }}
17 cancel-in-progress: true
18
19jobs:
20 # Resolve PR number for push events (bots pushing via API)
21 resolve-pr:
22 name: Resolve PR
23 if: ${{ github.event_name == 'push' }}
24 runs-on: ubuntu-latest
25 outputs:
26 pr_number: ${{ steps.find-pr.outputs.pr_number }}
27 is_fork: ${{ steps.find-pr.outputs.is_fork }}
28 steps:
29 - name: Find PR for branch
30 id: find-pr
31 uses: actions/github-script@v7
32 with:
33 script: |
34 const branch = context.ref.replace('refs/heads/', '');
35 const { data: prs } = await github.rest.pulls.list({
36 owner: context.repo.owner,
37 repo: context.repo.repo,
38 head: `${context.repo.owner}:${branch}`,
39 state: 'open',
40 });
41
42 if (prs.length === 0) {
43 core.setFailed(`No open PR found for branch ${branch}`);
44 return;
45 }
46
47 const pr = prs[0];
48 core.setOutput('pr_number', pr.number.toString());
49 core.setOutput('is_fork', (pr.head.repo.full_name !== pr.base.repo.full_name).toString());
50
51 pkg-preview:
52 name: Package Preview
53 if: ${{ github.repository_owner == 'cloudflare' }}
54 runs-on: ubuntu-latest
55 timeout-minutes: 15
56 steps:
57 - name: Checkout
58 uses: actions/checkout@v4
59 with:
60 fetch-depth: 1
61
62 - name: Install Dependencies
63 uses: ./.github/actions/install-dependencies
64 with:
65 filter: "@cloudflare/kumo..."
66
67 - name: Build @cloudflare/kumo
68 run: pnpm --filter @cloudflare/kumo build
69
70 - name: Publish preview package
71 run: pnpm dlx pkg-pr-new publish --pnpm --compact --no-template ./packages/kumo
72
73 # Stage 1: Build docs (runs for ALL PRs including forks).
74 # Produces an artifact consumed by either docs-deploy (internal) or
75 # the preview-deploy.yml workflow_run workflow (forks).
76 docs-build:
77 name: Docs Build
78 runs-on: ubuntu-latest
79 timeout-minutes: 15
80 steps:
81 - name: Checkout
82 uses: actions/checkout@v4
83 with:
84 fetch-depth: 1
85
86 - name: Install Dependencies
87 uses: ./.github/actions/install-dependencies
88 with:
89 filter: "@cloudflare/kumo-docs-astro..."
90
91 - name: Build @cloudflare/kumo
92 run: pnpm --filter @cloudflare/kumo build
93
94 - name: Build docs
95 run: pnpm --filter @cloudflare/kumo-docs-astro build
96
97 - name: Test docs
98 run: pnpm --filter @cloudflare/kumo-docs-astro test
99
100 - name: Upload docs artifact
101 uses: actions/upload-artifact@v4
102 with:
103 name: docs-preview-dist
104 path: packages/kumo-docs-astro/dist/
105 include-hidden-files: true
106 retention-days: 1
107
108 # Stage 2 (internal path): Deploy docs preview for non-fork PRs.
109 # Runs in the same workflow with secrets available.
110 # Fork PRs are handled by preview-deploy.yml (workflow_run).
111 docs-deploy:
112 name: Docs Deploy
113 needs: [docs-build, resolve-pr]
114 # Run for pull_request (non-fork) OR push events with resolved PR (non-fork)
115 if: |
116 always() &&
117 needs.docs-build.result == 'success' &&
118 (
119 (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) ||
120 (github.event_name == 'push' && needs.resolve-pr.result == 'success' && needs.resolve-pr.outputs.is_fork == 'false')
121 )
122 runs-on: ubuntu-latest
123 timeout-minutes: 10
124 outputs:
125 preview_url: ${{ steps.deploy.outputs.preview_url }}
126 pr_number: ${{ steps.set-pr.outputs.pr_number }}
127 steps:
128 - name: Set PR number
129 id: set-pr
130 run: |
131 if [ "${{ github.event_name }}" == "pull_request" ]; then
132 echo "pr_number=${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT"
133 else
134 echo "pr_number=${{ needs.resolve-pr.outputs.pr_number }}" >> "$GITHUB_OUTPUT"
135 fi
136
137 - name: Checkout
138 uses: actions/checkout@v4
139 with:
140 sparse-checkout: packages/kumo-docs-astro/wrangler.jsonc
141
142 - name: Download docs artifact
143 uses: actions/download-artifact@v4
144 with:
145 name: docs-preview-dist
146 path: packages/kumo-docs-astro/dist/
147
148 - name: Deploy docs preview
149 id: deploy
150 working-directory: packages/kumo-docs-astro
151 env:
152 CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
153 CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
154 PR_NUMBER: ${{ steps.set-pr.outputs.pr_number }}
155 run: |
156 COMMIT_SHORT="${GITHUB_SHA:0:7}"
157
158 # "wrangler versions upload" creates a preview version without
159 # routing production traffic. Safe to run on every PR.
160 VERSION_OUTPUT=$(npx wrangler versions upload --env="" --message "PR #${PR_NUMBER} (${COMMIT_SHORT})" 2>&1) || true
161 echo "$VERSION_OUTPUT"
162
163 # Verify upload succeeded
164 if ! echo "$VERSION_OUTPUT" | grep -q "Worker Version ID:"; then
165 echo "::error::wrangler versions upload failed -- no Worker Version ID in output"
166 exit 1
167 fi
168
169 # Extract preview URL from wrangler output
170 PREVIEW_URL=$(echo "$VERSION_OUTPUT" | grep -oE 'Version Preview URL: https://[^ ]+' | sed 's/Version Preview URL: //')
171
172 # Fallback: construct URL from version ID
173 if [ -z "$PREVIEW_URL" ]; then
174 VERSION_ID=$(echo "$VERSION_OUTPUT" | grep -oE 'Worker Version ID: [a-f0-9-]+' | sed 's/Worker Version ID: //')
175 if [ -n "$VERSION_ID" ]; then
176 VERSION_PREFIX=$(echo "$VERSION_ID" | cut -c1-8)
177 PREVIEW_URL="https://${VERSION_PREFIX}-kumo-docs.design-engineering.workers.dev"
178 fi
179 fi
180
181 if [ -z "$PREVIEW_URL" ]; then
182 echo "::error::Failed to determine docs preview URL"
183 exit 1
184 fi
185
186 echo "preview_url=$PREVIEW_URL" >> "$GITHUB_OUTPUT"
187
188 - name: Comment on PR
189 uses: actions/github-script@v7
190 env:
191 PREVIEW_URL: ${{ steps.deploy.outputs.preview_url }}
192 PR_NUMBER: ${{ steps.set-pr.outputs.pr_number }}
193 with:
194 script: |
195 const marker = '<!-- kumo-docs-preview -->';
196 const previewUrl = process.env.PREVIEW_URL;
197 const prNumber = parseInt(process.env.PR_NUMBER, 10);
198 const commitSha = context.sha.substring(0, 7);
199 const body = [
200 marker,
201 '### Docs Preview',
202 '',
203 `[View docs preview](${previewUrl})`,
204 '',
205 `Commit: \`${commitSha}\``,
206 ].join('\n');
207
208 const { data: comments } = await github.rest.issues.listComments({
209 owner: context.repo.owner,
210 repo: context.repo.repo,
211 issue_number: prNumber,
212 });
213
214 const existing = comments.find(c => c.body?.startsWith(marker));
215
216 if (existing) {
217 await github.rest.issues.updateComment({
218 owner: context.repo.owner,
219 repo: context.repo.repo,
220 comment_id: existing.id,
221 body,
222 });
223 } else {
224 await github.rest.issues.createComment({
225 owner: context.repo.owner,
226 repo: context.repo.repo,
227 issue_number: prNumber,
228 body,
229 });
230 }
231
232 visual-regression:
233 name: Visual Regression
234 needs: docs-deploy
235 if: always() && needs.docs-deploy.result == 'success' && needs.docs-deploy.outputs.preview_url != ''
236 runs-on: ubuntu-latest
237 timeout-minutes: 15
238 steps:
239 # Pin to main so that a PR modifying run-visual-regression.ts cannot
240 # execute its own version of the script with secrets in env.
241 - name: Checkout VR script from main
242 uses: actions/checkout@v4
243 with:
244 ref: main
245 sparse-checkout: |
246 ci/visual-regression
247 .github/actions/install-dependencies
248
249 # Fetch the PR's HEAD so git diff can detect changed files.
250 # (HEAD points to main after checkout, so we need the explicit SHA)
251 - name: Fetch PR head for git diff
252 run: git fetch --depth=1 origin ${{ github.event.pull_request.head.sha }}
253
254 - name: Install Dependencies
255 uses: ./.github/actions/install-dependencies
256 with:
257 filter: "@cloudflare/kumo..."
258
259 - name: Run Visual Regression
260 env:
261 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
262 GITHUB_PR_NUMBER: ${{ needs.docs-deploy.outputs.pr_number }}
263 GITHUB_REPOSITORY: ${{ github.repository }}
264 PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
265 BEFORE_URL: "https://kumo-ui.com"
266 AFTER_URL: ${{ needs.docs-deploy.outputs.preview_url }}
267 SCREENSHOT_API_KEY: ${{ secrets.SCREENSHOT_API_KEY }}
268 run: pnpm tsx ci/visual-regression/run-visual-regression.ts
269