Skip to content

Commit b370e34

Browse files
snomiaoclaude
andcommitted
[feat] Implement workflow_run architecture for CI comment/deploy separation
Restructures CI workflows to use workflow_run triggers, improving forked PR support and simplifying core testing workflows. ## Changes Made: ### New workflow_run triggered files: - pr-playwright-comment.yaml - Comments Playwright test results after Tests CI completion - pr-storybook-comment.yaml - Comments Storybook build status after Chromatic completion - pr-playwright-deploy.yaml - Deploys Playwright reports with secret access after Tests CI completion ### Simplified core workflows: - chromatic.yaml - Removed all commenting logic, focused on Chromatic testing only - test-ui.yaml - Removed deployment, commenting, and comment-summary job; focused on Playwright testing only ## Benefits: - ✅ Better forked PR support - workflow_run has access to secrets for deployment - ✅ Cleaner separation of concerns - testing vs commenting/deployment - ✅ Reduced complexity in core testing workflows - ✅ Improved reliability for external contributors 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent dedfadf commit b370e34

File tree

5 files changed

+297
-321
lines changed

5 files changed

+297
-321
lines changed

.github/workflows/chromatic.yaml

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ jobs:
1212
runs-on: ubuntu-latest
1313
# Only run for PRs from version-bump-* branches or manual triggers
1414
if: github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'version-bump-')
15-
permissions:
16-
pull-requests: write
17-
issues: write
1815
steps:
1916
- name: Checkout code
2017
uses: actions/checkout@v4
@@ -27,29 +24,6 @@ jobs:
2724
node-version: '20'
2825
cache: 'npm'
2926

30-
- name: Get current time
31-
id: current-time
32-
run: echo "time=$(date -u '+%m/%d/%Y, %I:%M:%S %p')" >> $GITHUB_OUTPUT
33-
34-
- name: Comment PR - Build Started
35-
if: github.event_name == 'pull_request'
36-
continue-on-error: true
37-
uses: edumserrano/find-create-or-update-comment@v3
38-
with:
39-
issue-number: ${{ github.event.pull_request.number }}
40-
body-includes: '<!-- STORYBOOK_BUILD_STATUS -->'
41-
comment-author: 'github-actions[bot]'
42-
edit-mode: append
43-
body: |
44-
<!-- STORYBOOK_BUILD_STATUS -->
45-
## 🎨 Storybook Build Status
46-
47-
🔄 **Building Storybook and running visual tests...**
48-
49-
⏳ Build started at: ${{ steps.current-time.outputs.time }} UTC
50-
51-
---
52-
*This comment will be updated when the build completes*
5327

5428
- name: Cache tool outputs
5529
uses: actions/cache@v4
@@ -76,37 +50,3 @@ jobs:
7650
autoAcceptChanges: 'main' # Auto-accept changes on main branch
7751
exitOnceUploaded: true # Don't wait for UI tests to complete
7852

79-
- name: Get completion time
80-
id: completion-time
81-
if: always()
82-
run: echo "time=$(date -u '+%m/%d/%Y, %I:%M:%S %p')" >> $GITHUB_OUTPUT
83-
84-
- name: Comment PR - Build Complete
85-
if: github.event_name == 'pull_request' && always()
86-
continue-on-error: true
87-
uses: edumserrano/find-create-or-update-comment@v3
88-
with:
89-
issue-number: ${{ github.event.pull_request.number }}
90-
body-includes: '<!-- STORYBOOK_BUILD_STATUS -->'
91-
comment-author: 'github-actions[bot]'
92-
edit-mode: replace
93-
body: |
94-
<!-- STORYBOOK_BUILD_STATUS -->
95-
## 🎨 Storybook Build Status
96-
97-
${{ steps.chromatic.outcome == 'success' && '✅' || '❌' }} **${{ steps.chromatic.outcome == 'success' && 'Build completed successfully!' || 'Build failed!' }}**
98-
99-
⏰ Completed at: ${{ steps.completion-time.outputs.time }} UTC
100-
101-
### 📊 Build Summary
102-
- **Components**: ${{ steps.chromatic.outputs.componentCount || '0' }}
103-
- **Stories**: ${{ steps.chromatic.outputs.testCount || '0' }}
104-
- **Visual changes**: ${{ steps.chromatic.outputs.changeCount || '0' }}
105-
- **Errors**: ${{ steps.chromatic.outputs.errorCount || '0' }}
106-
107-
### 🔗 Links
108-
${{ steps.chromatic.outputs.buildUrl && format('- [📸 View Chromatic Build]({0})', steps.chromatic.outputs.buildUrl) || '' }}
109-
${{ steps.chromatic.outputs.storybookUrl && format('- [📖 Preview Storybook]({0})', steps.chromatic.outputs.storybookUrl) || '' }}
110-
111-
---
112-
${{ steps.chromatic.outcome == 'success' && '🎉 Your Storybook is ready for review!' || '⚠️ Please check the workflow logs for error details.' }}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
name: PR Playwright Comment
2+
3+
on:
4+
workflow_run:
5+
workflows: ["Tests CI"]
6+
types: [completed]
7+
8+
env:
9+
DATE_FORMAT: '+%m/%d/%Y, %I:%M:%S %p'
10+
11+
jobs:
12+
comment-summary:
13+
runs-on: ubuntu-latest
14+
if: github.event.workflow_run.event == 'pull_request'
15+
permissions:
16+
pull-requests: write
17+
actions: read
18+
steps:
19+
- name: Get PR number
20+
id: pr
21+
uses: actions/github-script@v7
22+
with:
23+
script: |
24+
const { data: pullRequests } = await github.rest.pulls.list({
25+
owner: context.repo.owner,
26+
repo: context.repo.repo,
27+
state: 'open',
28+
head: `${context.repo.owner}:${context.payload.workflow_run.head_branch}`,
29+
});
30+
31+
if (pullRequests.length === 0) {
32+
console.log('No open PR found for this branch');
33+
return null;
34+
}
35+
36+
return pullRequests[0].number;
37+
38+
- name: Download all deployment info
39+
if: steps.pr.outputs.result != 'null'
40+
uses: actions/download-artifact@v4
41+
with:
42+
github-token: ${{ secrets.GITHUB_TOKEN }}
43+
run-id: ${{ github.event.workflow_run.id }}
44+
pattern: deployment-info-*
45+
merge-multiple: true
46+
path: deployment-info
47+
48+
- name: Get completion time
49+
id: completion-time
50+
run: echo "time=$(date -u '${{ env.DATE_FORMAT }}')" >> $GITHUB_OUTPUT
51+
52+
- name: Generate comment body
53+
if: steps.pr.outputs.result != 'null'
54+
id: comment-body
55+
run: |
56+
echo "<!-- PLAYWRIGHT_TEST_STATUS -->" > comment.md
57+
echo "## 🎭 Playwright Test Results" >> comment.md
58+
echo "" >> comment.md
59+
60+
# Check if all tests passed
61+
ALL_PASSED=true
62+
for file in deployment-info/*.txt; do
63+
if [ -f "$file" ]; then
64+
browser=$(basename "$file" .txt)
65+
info=$(cat "$file")
66+
exit_code=$(echo "$info" | cut -d'|' -f2)
67+
if [ "$exit_code" != "0" ]; then
68+
ALL_PASSED=false
69+
break
70+
fi
71+
fi
72+
done
73+
74+
if [ "$ALL_PASSED" = "true" ]; then
75+
echo "✅ **All tests passed across all browsers!**" >> comment.md
76+
else
77+
echo "❌ **Some tests failed!**" >> comment.md
78+
fi
79+
80+
echo "" >> comment.md
81+
echo "⏰ Completed at: ${{ steps.completion-time.outputs.time }} UTC" >> comment.md
82+
echo "" >> comment.md
83+
echo "### 📊 Test Reports by Browser" >> comment.md
84+
85+
for file in deployment-info/*.txt; do
86+
if [ -f "$file" ]; then
87+
browser=$(basename "$file" .txt)
88+
info=$(cat "$file")
89+
exit_code=$(echo "$info" | cut -d'|' -f2)
90+
url=$(echo "$info" | cut -d'|' -f3)
91+
92+
if [ "$exit_code" = "0" ]; then
93+
status="✅"
94+
else
95+
status="❌"
96+
fi
97+
98+
echo "- $status **$browser**: [View Report]($url)" >> comment.md
99+
fi
100+
done
101+
102+
echo "" >> comment.md
103+
echo "---" >> comment.md
104+
if [ "$ALL_PASSED" = "true" ]; then
105+
echo "🎉 Your tests are passing across all browsers!" >> comment.md
106+
else
107+
echo "⚠️ Please check the test reports for details on failures." >> comment.md
108+
fi
109+
110+
- name: Comment PR - Tests Complete
111+
if: steps.pr.outputs.result != 'null'
112+
continue-on-error: true
113+
uses: edumserrano/find-create-or-update-comment@v3
114+
with:
115+
issue-number: ${{ steps.pr.outputs.result }}
116+
body-includes: '<!-- PLAYWRIGHT_TEST_STATUS -->'
117+
comment-author: 'github-actions[bot]'
118+
edit-mode: replace
119+
body-path: comment.md
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
name: PR Playwright Deploy
2+
3+
on:
4+
workflow_run:
5+
workflows: ["Tests CI"]
6+
types: [completed]
7+
8+
jobs:
9+
deploy-reports:
10+
runs-on: ubuntu-latest
11+
if: github.event.workflow_run.event == 'pull_request'
12+
permissions:
13+
actions: read
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
browser: [chromium, chromium-2x, chromium-0.5x, mobile-chrome]
18+
steps:
19+
- name: Get PR info
20+
id: pr-info
21+
uses: actions/github-script@v7
22+
with:
23+
script: |
24+
const { data: pullRequests } = await github.rest.pulls.list({
25+
owner: context.repo.owner,
26+
repo: context.repo.repo,
27+
state: 'open',
28+
head: `${context.repo.owner}:${context.payload.workflow_run.head_branch}`,
29+
});
30+
31+
if (pullRequests.length === 0) {
32+
console.log('No open PR found for this branch');
33+
return { number: null, sanitized_branch: null };
34+
}
35+
36+
const pr = pullRequests[0];
37+
const branchName = context.payload.workflow_run.head_branch;
38+
const sanitizedBranch = branchName.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/--+/g, '-').replace(/^-|-$/g, '');
39+
40+
return {
41+
number: pr.number,
42+
sanitized_branch: sanitizedBranch
43+
};
44+
45+
- name: Set project name
46+
if: fromJSON(steps.pr-info.outputs.result).number != null
47+
id: project-name
48+
run: |
49+
if [ "${{ matrix.browser }}" = "chromium-0.5x" ]; then
50+
echo "name=comfyui-playwright-chromium-0-5x" >> $GITHUB_OUTPUT
51+
else
52+
echo "name=comfyui-playwright-${{ matrix.browser }}" >> $GITHUB_OUTPUT
53+
fi
54+
echo "branch=${{ fromJSON(steps.pr-info.outputs.result).sanitized_branch }}" >> $GITHUB_OUTPUT
55+
56+
- name: Download playwright report
57+
if: fromJSON(steps.pr-info.outputs.result).number != null
58+
uses: actions/download-artifact@v4
59+
with:
60+
github-token: ${{ secrets.GITHUB_TOKEN }}
61+
run-id: ${{ github.event.workflow_run.id }}
62+
name: playwright-report-${{ matrix.browser }}
63+
path: playwright-report
64+
65+
- name: Install Wrangler
66+
if: fromJSON(steps.pr-info.outputs.result).number != null
67+
run: npm install -g wrangler
68+
69+
- name: Deploy to Cloudflare Pages (${{ matrix.browser }})
70+
if: fromJSON(steps.pr-info.outputs.result).number != null
71+
id: cloudflare-deploy
72+
continue-on-error: true
73+
run: |
74+
# Retry logic for wrangler deploy (3 attempts)
75+
RETRY_COUNT=0
76+
MAX_RETRIES=3
77+
SUCCESS=false
78+
79+
while [ $RETRY_COUNT -lt $MAX_RETRIES ] && [ $SUCCESS = false ]; do
80+
RETRY_COUNT=$((RETRY_COUNT + 1))
81+
echo "Deployment attempt $RETRY_COUNT of $MAX_RETRIES..."
82+
83+
if npx wrangler pages deploy playwright-report --project-name=${{ steps.project-name.outputs.name }} --branch=${{ steps.project-name.outputs.branch }}; then
84+
SUCCESS=true
85+
echo "Deployment successful on attempt $RETRY_COUNT"
86+
else
87+
echo "Deployment failed on attempt $RETRY_COUNT"
88+
if [ $RETRY_COUNT -lt $MAX_RETRIES ]; then
89+
echo "Retrying in 10 seconds..."
90+
sleep 10
91+
fi
92+
fi
93+
done
94+
95+
if [ $SUCCESS = false ]; then
96+
echo "All deployment attempts failed"
97+
exit 1
98+
fi
99+
env:
100+
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
101+
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
name: PR Storybook Comment
2+
3+
on:
4+
workflow_run:
5+
workflows: ["Chromatic"]
6+
types: [completed]
7+
8+
jobs:
9+
comment-storybook:
10+
runs-on: ubuntu-latest
11+
if: github.event.workflow_run.event == 'pull_request'
12+
permissions:
13+
pull-requests: write
14+
actions: read
15+
steps:
16+
- name: Get PR number
17+
id: pr
18+
uses: actions/github-script@v7
19+
with:
20+
script: |
21+
const { data: pullRequests } = await github.rest.pulls.list({
22+
owner: context.repo.owner,
23+
repo: context.repo.repo,
24+
state: 'open',
25+
head: `${context.repo.owner}:${context.payload.workflow_run.head_branch}`,
26+
});
27+
28+
if (pullRequests.length === 0) {
29+
console.log('No open PR found for this branch');
30+
return null;
31+
}
32+
33+
return pullRequests[0].number;
34+
35+
- name: Get workflow run details
36+
if: steps.pr.outputs.result != 'null'
37+
id: workflow-run
38+
uses: actions/github-script@v7
39+
with:
40+
script: |
41+
const run = await github.rest.actions.getWorkflowRun({
42+
owner: context.repo.owner,
43+
repo: context.repo.repo,
44+
run_id: context.payload.workflow_run.id,
45+
});
46+
47+
return {
48+
conclusion: run.data.conclusion,
49+
html_url: run.data.html_url
50+
};
51+
52+
- name: Get completion time
53+
id: completion-time
54+
run: echo "time=$(date -u '+%m/%d/%Y, %I:%M:%S %p')" >> $GITHUB_OUTPUT
55+
56+
- name: Comment PR - Storybook Complete
57+
if: steps.pr.outputs.result != 'null'
58+
continue-on-error: true
59+
uses: edumserrano/find-create-or-update-comment@v3
60+
with:
61+
issue-number: ${{ steps.pr.outputs.result }}
62+
body-includes: '<!-- STORYBOOK_BUILD_STATUS -->'
63+
comment-author: 'github-actions[bot]'
64+
edit-mode: replace
65+
body: |
66+
<!-- STORYBOOK_BUILD_STATUS -->
67+
## 🎨 Storybook Build Status
68+
69+
${{ fromJSON(steps.workflow-run.outputs.result).conclusion == 'success' && '✅' || '❌' }} **${{ fromJSON(steps.workflow-run.outputs.result).conclusion == 'success' && 'Build completed successfully!' || 'Build failed!' }}**
70+
71+
⏰ Completed at: ${{ steps.completion-time.outputs.time }} UTC
72+
73+
### 🔗 Links
74+
- [📊 View Workflow Run](${{ fromJSON(steps.workflow-run.outputs.result).html_url }})
75+
76+
---
77+
${{ fromJSON(steps.workflow-run.outputs.result).conclusion == 'success' && '🎉 Your Storybook is ready for review!' || '⚠️ Please check the workflow logs for error details.' }}

0 commit comments

Comments
 (0)