1
- name : ' Chromatic'
1
+ name : Storybook and Chromatic CI
2
2
3
3
# - [Automate Chromatic with GitHub Actions • Chromatic docs]( https://www.chromatic.com/docs/github-actions/ )
4
4
8
8
branches : [main]
9
9
10
10
jobs :
11
+ # Post starting comment for non-forked PRs
12
+ comment-on-pr-start :
13
+ runs-on : ubuntu-latest
14
+ if : github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false
15
+ permissions :
16
+ pull-requests : write
17
+ steps :
18
+ - name : Checkout repository
19
+ uses : actions/checkout@v5
20
+
21
+ - name : Post starting comment
22
+ env :
23
+ GITHUB_TOKEN : ${{ github.token }}
24
+ run : |
25
+ chmod +x scripts/cicd/pr-storybook-deploy-and-comment.sh
26
+ ./scripts/cicd/pr-storybook-deploy-and-comment.sh \
27
+ "${{ github.event.pull_request.number }}" \
28
+ "${{ github.head_ref }}" \
29
+ "starting" \
30
+ "$(date -u '+%m/%d/%Y, %I:%M:%S %p')"
31
+
32
+ # Build Storybook for all PRs (free Cloudflare deployment)
33
+ storybook-build :
34
+ runs-on : ubuntu-latest
35
+ if : github.event_name == 'pull_request'
36
+ outputs :
37
+ conclusion : ${{ steps.job-status.outputs.conclusion }}
38
+ workflow-url : ${{ steps.workflow-url.outputs.url }}
39
+ steps :
40
+ - name : Checkout code
41
+ uses : actions/checkout@v5
42
+
43
+ - name : Install pnpm
44
+ uses : pnpm/action-setup@v4
45
+ with :
46
+ version : 10
47
+
48
+ - name : Setup Node.js
49
+ uses : actions/setup-node@v4
50
+ with :
51
+ node-version : ' 20'
52
+ cache : ' pnpm'
53
+
54
+ - name : Cache tool outputs
55
+ uses : actions/cache@v4
56
+ with :
57
+ path : |
58
+ .cache
59
+ storybook-static
60
+ tsconfig.tsbuildinfo
61
+ key : storybook-cache-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ hashFiles('src/**/*.{ts,vue,js}', '*.config.*', '.storybook/**/*') }}
62
+ restore-keys : |
63
+ storybook-cache-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}-
64
+ storybook-cache-${{ runner.os }}-
65
+ storybook-tools-cache-${{ runner.os }}-
66
+
67
+ - name : Install dependencies
68
+ run : pnpm install --frozen-lockfile
69
+
70
+ - name : Build Storybook
71
+ run : pnpm build-storybook
72
+
73
+ - name : Set job status
74
+ id : job-status
75
+ if : always()
76
+ run : |
77
+ echo "conclusion=${{ job.status }}" >> $GITHUB_OUTPUT
78
+
79
+ - name : Get workflow URL
80
+ id : workflow-url
81
+ if : always()
82
+ run : |
83
+ echo "url=${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" >> $GITHUB_OUTPUT
84
+
85
+ - name : Upload Storybook build
86
+ if : success() && github.event.pull_request.head.repo.fork == false
87
+ uses : actions/upload-artifact@v4
88
+ with :
89
+ name : storybook-static
90
+ path : storybook-static/
91
+ retention-days : 7
92
+
93
+ # Chromatic deployment only for version-bump-* branches or manual triggers
11
94
chromatic-deployment :
12
95
runs-on : ubuntu-latest
13
- # Only run for PRs from version-bump-* branches or manual triggers
14
- if : github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'version-bump-')
96
+ if : github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && startsWith(github.head_ref, 'version-bump-'))
97
+ outputs :
98
+ conclusion : ${{ steps.job-status.outputs.conclusion }}
99
+ workflow-url : ${{ steps.workflow-url.outputs.url }}
100
+ chromatic-build-url : ${{ steps.chromatic.outputs.buildUrl }}
101
+ chromatic-storybook-url : ${{ steps.chromatic.outputs.storybookUrl }}
15
102
steps :
16
103
- name : Checkout code
17
- uses : actions/checkout@v4
104
+ uses : actions/checkout@v5
18
105
with :
19
106
fetch-depth : 0 # Required for Chromatic baseline
20
107
29
116
node-version : ' 20'
30
117
cache : ' pnpm'
31
118
32
-
33
119
- name : Cache tool outputs
34
120
uses : actions/cache@v4
35
121
with :
@@ -54,4 +140,92 @@ jobs:
54
140
buildScriptName : build-storybook
55
141
autoAcceptChanges : ' main' # Auto-accept changes on main branch
56
142
exitOnceUploaded : true # Don't wait for UI tests to complete
143
+ onlyChanged : true # Only capture changed stories
144
+
145
+ - name : Set job status
146
+ id : job-status
147
+ if : always()
148
+ run : |
149
+ echo "conclusion=${{ job.status }}" >> $GITHUB_OUTPUT
150
+
151
+ - name : Get workflow URL
152
+ id : workflow-url
153
+ if : always()
154
+ run : |
155
+ echo "url=${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" >> $GITHUB_OUTPUT
156
+
157
+ # Deploy and comment for non-forked PRs only
158
+ deploy-and-comment :
159
+ needs : [storybook-build]
160
+ runs-on : ubuntu-latest
161
+ if : github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false && always()
162
+ permissions :
163
+ pull-requests : write
164
+ contents : read
165
+ steps :
166
+ - name : Checkout repository
167
+ uses : actions/checkout@v5
168
+
169
+ - name : Download Storybook build
170
+ if : needs.storybook-build.outputs.conclusion == 'success'
171
+ uses : actions/download-artifact@v4
172
+ with :
173
+ name : storybook-static
174
+ path : storybook-static
175
+
176
+ - name : Make deployment script executable
177
+ run : chmod +x scripts/cicd/pr-storybook-deploy-and-comment.sh
178
+
179
+ - name : Deploy Storybook and comment on PR
180
+ env :
181
+ CLOUDFLARE_API_TOKEN : ${{ secrets.CLOUDFLARE_API_TOKEN }}
182
+ CLOUDFLARE_ACCOUNT_ID : ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
183
+ GITHUB_TOKEN : ${{ github.token }}
184
+ WORKFLOW_CONCLUSION : ${{ needs.storybook-build.outputs.conclusion }}
185
+ WORKFLOW_URL : ${{ needs.storybook-build.outputs.workflow-url }}
186
+ run : |
187
+ ./scripts/cicd/pr-storybook-deploy-and-comment.sh \
188
+ "${{ github.event.pull_request.number }}" \
189
+ "${{ github.head_ref }}" \
190
+ "completed"
57
191
192
+ # Update comment with Chromatic URLs for version-bump branches
193
+ update-comment-with-chromatic :
194
+ needs : [chromatic-deployment, deploy-and-comment]
195
+ runs-on : ubuntu-latest
196
+ if : github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false && startsWith(github.head_ref, 'version-bump-') && needs.chromatic-deployment.outputs.chromatic-build-url != ''
197
+ permissions :
198
+ pull-requests : write
199
+ steps :
200
+ - name : Update comment with Chromatic URLs
201
+ uses : actions/github-script@v7
202
+ with :
203
+ script : |
204
+ const buildUrl = '${{ needs.chromatic-deployment.outputs.chromatic-build-url }}';
205
+ const storybookUrl = '${{ needs.chromatic-deployment.outputs.chromatic-storybook-url }}';
206
+
207
+ // Find the existing Storybook comment
208
+ const { data: comments } = await github.rest.issues.listComments({
209
+ owner: context.repo.owner,
210
+ repo: context.repo.repo,
211
+ issue_number: ${{ github.event.pull_request.number }}
212
+ });
213
+
214
+ const storybookComment = comments.find(comment =>
215
+ comment.body.includes('<!-- STORYBOOK_BUILD_STATUS -->')
216
+ );
217
+
218
+ if (storybookComment && buildUrl && storybookUrl) {
219
+ // Append Chromatic info to existing comment
220
+ const updatedBody = storybookComment.body.replace(
221
+ /---\n(.*)$/s,
222
+ `---\n### 🎨 Chromatic Visual Tests\n- 📊 [View Chromatic Build](${buildUrl})\n- 📚 [View Chromatic Storybook](${storybookUrl})\n\n$1`
223
+ );
224
+
225
+ await github.rest.issues.updateComment({
226
+ owner: context.repo.owner,
227
+ repo: context.repo.repo,
228
+ comment_id: storybookComment.id,
229
+ body: updatedBody
230
+ });
231
+ }
0 commit comments