Skip to content

Commit 2e11a58

Browse files
committed
docs: update CICD docs and deploy.yml.example with PostHog vars
1 parent 4cc6de3 commit 2e11a58

2 files changed

Lines changed: 152 additions & 10 deletions

File tree

.github/workflows/deploy.yml.example

Lines changed: 150 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,18 @@ on:
1313
options:
1414
- production
1515
- staging
16+
skip_build:
17+
description: 'Skip build and use latest images'
18+
type: boolean
19+
default: false
20+
force_build_web:
21+
description: 'Force web image rebuild'
22+
type: boolean
23+
default: false
24+
force_build_crawler:
25+
description: 'Force crawler image rebuild'
26+
type: boolean
27+
default: false
1628

1729
env:
1830
NODE_VERSION: '20'
@@ -21,12 +33,103 @@ env:
2133
IMAGE_NAME: ${{ github.repository }}
2234

2335
jobs:
36+
# ===========================================
37+
# JOB 0: DETECT CHANGES
38+
# ===========================================
39+
# Smart change detection - only rebuild what changed
40+
detect-changes:
41+
name: Detect Changes
42+
runs-on: ubuntu-latest
43+
outputs:
44+
web: ${{ steps.filter.outputs.web }}
45+
crawler: ${{ steps.filter.outputs.crawler }}
46+
verify: ${{ steps.filter.outputs.verify }}
47+
infra: ${{ steps.filter.outputs.infra }}
48+
should_build_web: ${{ steps.should-build.outputs.web }}
49+
should_build_crawler: ${{ steps.should-build.outputs.crawler }}
50+
steps:
51+
- uses: actions/checkout@v4
52+
53+
- uses: dorny/paths-filter@v2
54+
id: filter
55+
with:
56+
filters: |
57+
web:
58+
- 'apps/web/**'
59+
- 'packages/**'
60+
- 'config/**'
61+
- 'Dockerfile.web'
62+
crawler:
63+
- 'apps/crawler/**'
64+
- 'packages/**'
65+
- 'config/**'
66+
- 'Dockerfile.crawler'
67+
verify:
68+
- 'tools/verify/**'
69+
infra:
70+
- 'docker-compose.yml'
71+
- 'docker-compose.prod.yml'
72+
- 'docker-compose.cloud-prod.yml'
73+
- 'docker/**'
74+
75+
- name: Determine what to build
76+
id: should-build
77+
run: |
78+
# Web: build if web files changed, force requested, or manual dispatch without skip
79+
WEB_CHANGED="${{ steps.filter.outputs.web }}"
80+
CRAWLER_CHANGED="${{ steps.filter.outputs.crawler }}"
81+
SKIP_BUILD="${{ inputs.skip_build }}"
82+
FORCE_WEB="${{ inputs.force_build_web }}"
83+
FORCE_CRAWLER="${{ inputs.force_build_crawler }}"
84+
IS_MANUAL="${{ github.event_name == 'workflow_dispatch' }}"
85+
86+
# Default to building on push if changed, or on manual dispatch unless skip_build
87+
if [ "$SKIP_BUILD" = "true" ]; then
88+
BUILD_WEB="false"
89+
BUILD_CRAWLER="false"
90+
elif [ "$FORCE_WEB" = "true" ]; then
91+
BUILD_WEB="true"
92+
elif [ "$IS_MANUAL" = "true" ] && [ "$WEB_CHANGED" != "true" ]; then
93+
# Manual dispatch without force - still build if explicitly requested
94+
BUILD_WEB="false"
95+
else
96+
BUILD_WEB="$WEB_CHANGED"
97+
fi
98+
99+
if [ "$SKIP_BUILD" = "true" ]; then
100+
BUILD_CRAWLER="false"
101+
elif [ "$FORCE_CRAWLER" = "true" ]; then
102+
BUILD_CRAWLER="true"
103+
elif [ "$IS_MANUAL" = "true" ] && [ "$CRAWLER_CHANGED" != "true" ]; then
104+
BUILD_CRAWLER="false"
105+
else
106+
BUILD_CRAWLER="$CRAWLER_CHANGED"
107+
fi
108+
109+
# On push events, if nothing specific changed, build both (safety)
110+
if [ "$IS_MANUAL" != "true" ] && [ "$WEB_CHANGED" != "true" ] && [ "$CRAWLER_CHANGED" != "true" ]; then
111+
echo "No specific changes detected on push - building both for safety"
112+
BUILD_WEB="true"
113+
BUILD_CRAWLER="true"
114+
fi
115+
116+
echo "web=$BUILD_WEB" >> $GITHUB_OUTPUT
117+
echo "crawler=$BUILD_CRAWLER" >> $GITHUB_OUTPUT
118+
119+
echo "Build decisions:"
120+
echo " Web changed: $WEB_CHANGED -> Build web: $BUILD_WEB"
121+
echo " Crawler changed: $CRAWLER_CHANGED -> Build crawler: $BUILD_CRAWLER"
122+
echo " Skip build: $SKIP_BUILD"
123+
echo " Force web: $FORCE_WEB"
124+
echo " Force crawler: $FORCE_CRAWLER"
125+
24126
# ===========================================
25127
# JOB 1: DETECT CONFIGURATION
26128
# ===========================================
27129
detect-config:
28130
name: Detect Configuration
29131
runs-on: ubuntu-latest
132+
environment: production
30133
outputs:
31134
secrets_source: ${{ steps.detect.outputs.secrets_source }}
32135
ssm_param_name: ${{ steps.detect.outputs.ssm_param_name }}
@@ -115,7 +218,11 @@ jobs:
115218
build-verify-binaries:
116219
name: Build Verification Binaries
117220
runs-on: ubuntu-latest
118-
needs: detect-config
221+
needs: [detect-changes, detect-config]
222+
# Only build if web will be built (binaries go in web image) or verify tools changed
223+
if: |
224+
needs.detect-changes.outputs.should_build_web == 'true' ||
225+
needs.detect-changes.outputs.verify == 'true'
119226

120227
steps:
121228
- name: Checkout
@@ -189,8 +296,15 @@ jobs:
189296
build-and-push:
190297
name: Build & Push Images
191298
runs-on: ubuntu-latest
192-
needs: [detect-config, build-verify-binaries]
193-
if: always() && needs.detect-config.result == 'success' && needs.build-verify-binaries.result == 'success'
299+
needs: [detect-changes, detect-config, build-verify-binaries]
300+
# Run if at least one image needs building and config is ready
301+
# build-verify-binaries may be skipped if only crawler changed
302+
if: |
303+
always() &&
304+
needs.detect-config.result == 'success' &&
305+
(needs.build-verify-binaries.result == 'success' || needs.build-verify-binaries.result == 'skipped') &&
306+
(needs.detect-changes.outputs.should_build_web == 'true' || needs.detect-changes.outputs.should_build_crawler == 'true')
307+
environment: production
194308
permissions:
195309
contents: read
196310
packages: write
@@ -200,14 +314,16 @@ jobs:
200314
- name: Checkout
201315
uses: actions/checkout@v4
202316

203-
# Download verification binaries BEFORE building Docker image
317+
# Download verification binaries BEFORE building Docker image (only if building web)
204318
- name: Download verification binaries
319+
if: needs.detect-changes.outputs.should_build_web == 'true' && needs.build-verify-binaries.result == 'success'
205320
uses: actions/download-artifact@v4
206321
with:
207322
name: verify-binaries
208323
path: apps/web/public/verify/
209324

210325
- name: Verify binaries were downloaded
326+
if: needs.detect-changes.outputs.should_build_web == 'true' && needs.build-verify-binaries.result == 'success'
211327
run: |
212328
echo "Verification binaries:"
213329
ls -lh apps/web/public/verify/
@@ -217,6 +333,12 @@ jobs:
217333
fi
218334
echo "Verification binaries ready for Docker build"
219335

336+
- name: Create placeholder for verify binaries (crawler-only build)
337+
if: needs.detect-changes.outputs.should_build_web != 'true'
338+
run: |
339+
echo "Skipping verify binaries - not building web image"
340+
mkdir -p apps/web/public/verify/
341+
220342
# SECURITY: Fetch secrets directly (no artifacts)
221343
- name: Fetch secrets from AWS SSM
222344
if: needs.detect-config.outputs.secrets_source == 'aws-ssm'
@@ -282,6 +404,8 @@ jobs:
282404
echo "NEXT_PUBLIC_TURNSTILE_SITE_KEY=$NEXT_PUBLIC_TURNSTILE_SITE_KEY" >> $GITHUB_OUTPUT
283405
echo "NEXT_PUBLIC_ENABLE_TURNSTILE=$NEXT_PUBLIC_ENABLE_TURNSTILE" >> $GITHUB_OUTPUT
284406
echo "NEXT_PUBLIC_TURNSTILE_PROTECTED_ACTIONS=$NEXT_PUBLIC_TURNSTILE_PROTECTED_ACTIONS" >> $GITHUB_OUTPUT
407+
echo "NEXT_PUBLIC_POSTHOG_KEY=$NEXT_PUBLIC_POSTHOG_KEY" >> $GITHUB_OUTPUT
408+
echo "NEXT_PUBLIC_POSTHOG_HOST=$NEXT_PUBLIC_POSTHOG_HOST" >> $GITHUB_OUTPUT
285409

286410
echo "Extracted NEXT_PUBLIC_* variables for build"
287411

@@ -362,6 +486,7 @@ jobs:
362486

363487
- name: Extract metadata for web
364488
id: meta-web
489+
if: needs.detect-changes.outputs.should_build_web == 'true'
365490
uses: docker/metadata-action@v5
366491
with:
367492
images: ${{ steps.registry.outputs.url }}/${{ steps.registry-config.outputs.image_base }}web
@@ -371,6 +496,7 @@ jobs:
371496
type=raw,value=latest,enable={{is_default_branch}}
372497

373498
- name: Build and push web image
499+
if: needs.detect-changes.outputs.should_build_web == 'true'
374500
uses: docker/build-push-action@v6
375501
with:
376502
context: .
@@ -386,9 +512,16 @@ jobs:
386512
NEXT_PUBLIC_TURNSTILE_SITE_KEY=${{ steps.build-env.outputs.NEXT_PUBLIC_TURNSTILE_SITE_KEY }}
387513
NEXT_PUBLIC_ENABLE_TURNSTILE=${{ steps.build-env.outputs.NEXT_PUBLIC_ENABLE_TURNSTILE }}
388514
NEXT_PUBLIC_TURNSTILE_PROTECTED_ACTIONS=${{ steps.build-env.outputs.NEXT_PUBLIC_TURNSTILE_PROTECTED_ACTIONS }}
515+
NEXT_PUBLIC_POSTHOG_KEY=${{ steps.build-env.outputs.NEXT_PUBLIC_POSTHOG_KEY }}
516+
NEXT_PUBLIC_POSTHOG_HOST=${{ steps.build-env.outputs.NEXT_PUBLIC_POSTHOG_HOST }}
517+
518+
- name: Skip web build
519+
if: needs.detect-changes.outputs.should_build_web != 'true'
520+
run: echo "Skipping web image build - no web changes detected"
389521

390522
- name: Extract metadata for crawler
391523
id: meta-crawler
524+
if: needs.detect-changes.outputs.should_build_crawler == 'true'
392525
uses: docker/metadata-action@v5
393526
with:
394527
images: ${{ steps.registry.outputs.url }}/${{ steps.registry-config.outputs.image_base }}crawler
@@ -398,6 +531,7 @@ jobs:
398531
type=raw,value=latest,enable={{is_default_branch}}
399532

400533
- name: Build and push crawler image
534+
if: needs.detect-changes.outputs.should_build_crawler == 'true'
401535
uses: docker/build-push-action@v6
402536
with:
403537
context: .
@@ -408,6 +542,10 @@ jobs:
408542
cache-from: type=gha
409543
cache-to: type=gha,mode=max
410544

545+
- name: Skip crawler build
546+
if: needs.detect-changes.outputs.should_build_crawler != 'true'
547+
run: echo "Skipping crawler image build - no crawler changes detected"
548+
411549
# SECURITY: Clean up deployment.env - do NOT upload as artifact
412550
- name: Clean up secrets
413551
if: always()
@@ -419,11 +557,13 @@ jobs:
419557
backup:
420558
name: Backup Database
421559
runs-on: ubuntu-latest
422-
needs: [detect-config, build-and-push]
560+
needs: [detect-changes, detect-config, build-and-push]
423561
if: |
562+
always() &&
424563
needs.detect-config.outputs.backup_enabled == 'true' &&
425564
needs.detect-config.outputs.deployment_mode == 'self-hosted-docker' &&
426-
github.ref == 'refs/heads/master'
565+
github.ref == 'refs/heads/master' &&
566+
(needs.build-and-push.result == 'success' || needs.build-and-push.result == 'skipped')
427567
environment: production
428568

429569
steps:
@@ -465,11 +605,11 @@ jobs:
465605
deploy:
466606
name: Deploy to Server
467607
runs-on: ubuntu-latest
468-
needs: [detect-config, build-verify-binaries, build-and-push, backup]
608+
needs: [detect-changes, detect-config, build-verify-binaries, build-and-push, backup]
469609
if: |
470610
always() &&
471611
github.ref == 'refs/heads/master' &&
472-
needs.build-and-push.result == 'success' &&
612+
(needs.build-and-push.result == 'success' || needs.build-and-push.result == 'skipped') &&
473613
(needs.backup.result == 'success' || needs.backup.result == 'skipped')
474614
environment: production
475615

@@ -697,7 +837,7 @@ jobs:
697837
health-check:
698838
name: Health Check
699839
runs-on: ubuntu-latest
700-
needs: [detect-config, deploy]
840+
needs: [detect-changes, detect-config, deploy]
701841
if: |
702842
always() &&
703843
needs.detect-config.outputs.health_check_enabled == 'true' &&
@@ -748,7 +888,7 @@ jobs:
748888
rollback:
749889
name: Rollback Deployment
750890
runs-on: ubuntu-latest
751-
needs: [detect-config, backup, deploy, health-check]
891+
needs: [detect-changes, detect-config, backup, deploy, health-check]
752892
if: |
753893
always() &&
754894
needs.detect-config.outputs.rollback_enabled == 'true' &&

docs/CICD.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ NEXT_PUBLIC_SUPABASE_URL=...
188188
NEXT_PUBLIC_SUPABASE_ANON_KEY=...
189189
SUPABASE_SERVICE_ROLE_KEY=...
190190
TURNSTILE_SECRET_KEY=... # Cloudflare Turnstile (if enabled)
191+
NEXT_PUBLIC_POSTHOG_KEY=... # PostHog analytics (optional)
192+
NEXT_PUBLIC_POSTHOG_HOST=... # e.g., https://eu.i.posthog.com
191193
POSTGRES_PASSWORD=...
192194
JWT_SECRET=...
193195
SMTP_HOST=...

0 commit comments

Comments
 (0)