Skip to content

Commit 7bbd970

Browse files
Dbochmanclaude
andcommitted
ci(deploy): add fast-path for content-only deploys
Content-only changes (blog posts, kanban cards, RSS/sitemap) now skip tests, Playwright, Sentry upload, security audit, and bundle size check. Cuts deploy time from ~10min to ~2min for content edits. Adds a detect-changes job that whitelists content file patterns and gates 12 steps with conditional execution. Unknown file patterns always trigger the full pipeline. Also removes paths-ignore for **.md so kanban card changes actually trigger deploys. [skip-review] Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent e6e4ba5 commit 7bbd970

1 file changed

Lines changed: 57 additions & 6 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,51 @@ on:
44
push:
55
branches:
66
- main
7-
paths-ignore:
8-
- '**.md'
9-
- 'docs/**'
107

118
concurrency:
129
group: ${{ github.workflow }}-${{ github.ref }}
1310
cancel-in-progress: true
1411

1512
jobs:
13+
detect-changes:
14+
runs-on: ubuntu-latest
15+
outputs:
16+
is_content_only: ${{ steps.check.outputs.content_only }}
17+
steps:
18+
- uses: actions/checkout@v6
19+
with:
20+
fetch-depth: 10
21+
- name: Detect content-only changes
22+
id: check
23+
run: |
24+
BEFORE=${{ github.event.before }}
25+
if [ "$BEFORE" = "0000000000000000000000000000000000000000" ]; then
26+
echo "content_only=false" >> "$GITHUB_OUTPUT"
27+
exit 0
28+
fi
29+
if ! git cat-file -e "$BEFORE" 2>/dev/null; then
30+
echo "content_only=false" >> "$GITHUB_OUTPUT"
31+
exit 0
32+
fi
33+
CHANGED_FILES=$(git diff --name-only "$BEFORE" HEAD)
34+
echo "Changed files:"
35+
echo "$CHANGED_FILES"
36+
CONTENT_ONLY=true
37+
while IFS= read -r file; do
38+
case "$file" in
39+
content/blog/*.txt|content/kanban/*.md|content/kanban/**/*.md) ;;
40+
src/generated/*) ;;
41+
public/rss.xml|public/sitemap.xml|public/atom.xml) ;;
42+
public/og-images/*) ;;
43+
.claude/*|*.md) ;;
44+
*) CONTENT_ONLY=false; break ;;
45+
esac
46+
done <<< "$CHANGED_FILES"
47+
echo "content_only=$CONTENT_ONLY" >> "$GITHUB_OUTPUT"
48+
1649
build-and-test:
1750
runs-on: ubuntu-latest
51+
needs: detect-changes
1852
steps:
1953
- name: Checkout source
2054
uses: actions/checkout@v6
@@ -36,26 +70,37 @@ jobs:
3670
restore-keys: |
3771
mdx-
3872
73+
- name: Build mode
74+
run: |
75+
if [ "${{ needs.detect-changes.outputs.is_content_only }}" = "true" ]; then
76+
echo "::notice::Fast-path content-only deploy"
77+
else
78+
echo "::notice::Full build and test pipeline"
79+
fi
80+
3981
- name: Cache Playwright browsers
82+
if: needs.detect-changes.outputs.is_content_only != 'true'
4083
id: playwright-cache
4184
uses: actions/cache@v5
4285
with:
4386
path: ~/.cache/ms-playwright
4487
key: ${{ runner.os }}-playwright-${{ hashFiles('package-lock.json') }}
4588

4689
- name: Install Playwright browsers
47-
if: steps.playwright-cache.outputs.cache-hit != 'true'
90+
if: needs.detect-changes.outputs.is_content_only != 'true' && steps.playwright-cache.outputs.cache-hit != 'true'
4891
run: npx playwright install chromium --with-deps
4992

5093
- name: Install Playwright deps only
51-
if: steps.playwright-cache.outputs.cache-hit == 'true'
94+
if: needs.detect-changes.outputs.is_content_only != 'true' && steps.playwright-cache.outputs.cache-hit == 'true'
5295
run: npx playwright install-deps chromium
5396

5497
- name: Security audit
98+
if: needs.detect-changes.outputs.is_content_only != 'true'
5599
run: npm audit --audit-level=high --omit=dev
56100
continue-on-error: true
57101

58102
- name: Run unit tests
103+
if: needs.detect-changes.outputs.is_content_only != 'true'
59104
run: npm test
60105

61106
- name: Build site
@@ -64,6 +109,7 @@ jobs:
64109
GITHUB_SHA: ${{ github.sha }}
65110

66111
- name: Upload source maps to Sentry
112+
if: needs.detect-changes.outputs.is_content_only != 'true'
67113
env:
68114
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
69115
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
@@ -74,12 +120,14 @@ jobs:
74120
npx sentry-cli releases finalize ${{ github.sha }}
75121
76122
- name: Remove source maps from build
123+
if: needs.detect-changes.outputs.is_content_only != 'true'
77124
run: find ./dist -name '*.map' -delete
78125

79126
# Bundle size check uses raw (uncompressed) file sizes as a build guard.
80127
# This catches accidental bloat from new dependencies or unoptimized code.
81128
# Actual transfer sizes are ~70% smaller due to gzip/brotli compression.
82129
- name: Check bundle size budget
130+
if: needs.detect-changes.outputs.is_content_only != 'true'
83131
run: |
84132
node -e "
85133
const fs = require('fs');
@@ -135,14 +183,17 @@ jobs:
135183
"
136184
137185
- name: Start preview server
186+
if: needs.detect-changes.outputs.is_content_only != 'true'
138187
run: npm run preview &
139188
env:
140189
CI: true
141190

142191
- name: Wait for server to be ready
192+
if: needs.detect-changes.outputs.is_content_only != 'true'
143193
run: npx wait-on http://localhost:4173 --timeout 30000
144194

145195
- name: Run smoke tests
196+
if: needs.detect-changes.outputs.is_content_only != 'true'
146197
run: BASE_URL=http://localhost:4173 npx playwright test --grep @smoke
147198
env:
148199
CI: true
@@ -155,7 +206,7 @@ jobs:
155206
retention-days: 1
156207

157208
- name: Upload test results
158-
if: failure()
209+
if: failure() && needs.detect-changes.outputs.is_content_only != 'true'
159210
uses: actions/upload-artifact@v6
160211
with:
161212
name: playwright-test-results

0 commit comments

Comments
 (0)