11name : Visual Diff
22
33on :
4- pull_request : {}
4+ pull_request :
5+ types : [labeled, unlabeled, opened, synchronize, reopened]
56
67concurrency :
78 group : visual-diff-${{ github.head_ref || github.ref }}
@@ -11,39 +12,71 @@ jobs:
1112 baseline :
1213 name : Baseline
1314 runs-on : ubuntu-latest
15+ outputs :
16+ ref : ${{ steps.ref.outputs.ref }}
1417 steps :
1518 - uses : actions/checkout@v6
1619 with :
1720 ref : ${{ github.base_ref }}
21+ - id : ref
22+ run : |
23+ echo "$(git rev-parse HEAD)"
24+ echo "ref=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
25+ - name : Cache Screenshots
26+ id : screenshot-cache
27+ uses : actions/cache@v5
28+ with :
29+ path : build
30+ key : screenshots-${{ steps.ref.outputs.ref }}
1831 - uses : pnpm/action-setup@v4
1932 - uses : actions/setup-node@v6
2033 with :
2134 node-version : 24
2235 cache : pnpm
23- - run : pnpm install
24- - run : pnpm exec playwright install --with-deps
36+ - name : Install Dependencies
37+ if : steps.screenshot-cache.outputs.cache-hit != 'true'
38+ run : |
39+ pnpm install
40+ pnpm exec playwright install --with-deps
2541 - name : Capture Screenshots
42+ if : steps.screenshot-cache.outputs.cache-hit != 'true'
2643 run : pnpm run test:screenshots
27- - uses : actions/upload-artifact@v6
44+ - uses : actions/upload-artifact@v7
2845 with :
2946 name : baseline
3047 path : build
3148
3249 candidate :
3350 name : Candidate
3451 runs-on : ubuntu-latest
52+ outputs :
53+ ref : ${{ steps.ref.outputs.ref }}
3554 steps :
3655 - uses : actions/checkout@v6
56+ - id : ref
57+ run : |
58+ echo "$(git rev-parse HEAD)"
59+ echo "ref=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
60+ - name : Cache Screenshots
61+ id : screenshot-cache
62+ uses : actions/cache@v5
63+ with :
64+ path : build
65+ key : screenshots-${{ steps.ref.outputs.ref }}-${{ matrix.name }}
3766 - uses : pnpm/action-setup@v4
3867 - uses : actions/setup-node@v6
3968 with :
4069 node-version : 24
4170 cache : pnpm
42- - run : pnpm install
43- - run : pnpm exec playwright install --with-deps
71+ - name : Install Dependencies
72+ if : steps.screenshot-cache.outputs.cache-hit != 'true'
73+ run : |
74+ pnpm install
75+ pnpm exec playwright install --with-deps
4476 - name : Capture Screenshots
45- run : pnpm run test:screenshots
46- - uses : actions/upload-artifact@v6
77+ if : steps.screenshot-cache.outputs.cache-hit != 'true'
78+ run : pnpm test:screenshots
79+ - uses : actions/upload-artifact@v7
4780 with :
4881 name : candidate
4982 path : build
@@ -54,35 +87,68 @@ jobs:
5487 runs-on : ubuntu-latest
5588 env :
5689 OUTPUT_DIR : visual-diff-${{ github.event.pull_request.number }}
90+ BASELINE_REF : ${{needs.baseline.outputs.ref}}
91+ CANDIDATE_REF : ${{needs.candidate.outputs.ref}}
5792 steps :
5893 - uses : actions/checkout@v6
59- - uses : actions/download-artifact@v7
60- - run : ls -lh baseline candidate
61- - uses : pnpm/action-setup@v4
6294 - uses : actions/setup-node@v6
6395 with :
6496 node-version : 24
65- - run : pnpm install
66- - run : pnpm build
97+ - uses : pnpm/action-setup@v4
98+ - name : Restore Comparison Cache
99+ id : comparison-cache
100+ uses : actions/cache/restore@v5
101+ with :
102+ path : |
103+ ${{ env.OUTPUT_DIR }}
104+ results
105+ key : comparison-${{ env.BASELINE_REF }}-${{ env.CANDIDATE_REF }}
106+ - uses : actions/download-artifact@v8
107+ if : steps.comparison-cache.outputs.cache-hit != 'true'
108+ - run : ls -lh baseline candidate 2>/dev/null || true
67109 - run : |
68110 mkdir -p ./results
69111 echo ${{ github.event.pull_request.number }} > ./results/pr_number
112+ - run : pnpm install
113+ if : steps.comparison-cache.outputs.cache-hit != 'true'
114+ - run : pnpm build
115+ if : steps.comparison-cache.outputs.cache-hit != 'true'
70116 - name : Create Visual Diff
71- run : node ./dist/bin/visual-differ.js baseline candidate ${{ env.OUTPUT_DIR }} > results/visual-diff.txt
72- - if : always()
73- run : cp ${{ env.OUTPUT_DIR }}/report.md results/
74- - if : always()
75- run : cat results/report.md results/visual-diff.txt
76- - uses : actions/upload-artifact@v6
117+ if : steps.comparison-cache.outputs.cache-hit != 'true'
118+ run : |
119+ set +e
120+ node ./dist/bin/visual-differ.js --threshold=0.1 baseline candidate ${{ env.OUTPUT_DIR }} > results/visual-diff.txt
121+ exit_code=$?
122+ echo $exit_code > ./results/exit_code
123+ cp ${{ env.OUTPUT_DIR }}/report.md results/
124+ cat results/report.md results/visual-diff.txt
125+ - uses : actions/upload-artifact@v7
77126 id : upload-output
78- if : always()
79127 with :
80128 name : ${{ env.OUTPUT_DIR }}
81129 path : ${{ env.OUTPUT_DIR }}
82- - if : always()
83- run : echo ${{ steps.upload-output.outputs.artifact-url }} > ./results/artifact_url
84- - uses : actions/upload-artifact@v6
85- if : always()
130+ - run : |
131+ echo ${{ steps.upload-output.outputs.artifact-url }} > ./results/artifact_url
132+ echo ${{ contains(github.event.pull_request.labels.*.name, 'approve visual diff') }} > ./results/approved
133+ - name : Save Comparison Cache
134+ if : steps.comparison-cache.outputs.cache-hit != 'true'
135+ uses : actions/cache/save@v5
136+ with :
137+ path : |
138+ ${{ env.OUTPUT_DIR }}
139+ results
140+ key : ${{ steps.comparison-cache.outputs.cache-primary-key }}
141+ - uses : actions/upload-artifact@v7
86142 with :
87143 name : results
88144 path : results
145+ - name : Check Status
146+ run : |
147+ exitCode=$(cat ./results/exit_code)
148+ approved=$(cat ./results/approved)
149+ echo "visual-differ exit code: $exitCode"
150+ echo "approve visual diff label present: $approved"
151+ if [ "$exitCode" != "0" ] && [ "$approved" != "true" ]; then
152+ echo "Visual diff detected and 'approve visual diff' label not present."
153+ exit 1
154+ fi
0 commit comments