Skip to content

Commit 2d7df61

Browse files
authored
feat: add turbo-scm-base input for Turbo monorepo support in workflows and documentation (#196)
Adds Turbo monorepo support and monorepo-aware build artifact handling to the centralized frontend workflows. ## Why `performance-analytics` is a Turborepo monorepo where builds output to `apps/*/dist/` rather than a single root `dist/` directory. The existing `build-output-dir` input only supports a single directory path, which breaks both artifact upload (nothing found at root `dist/`) and download (`upload-artifact@v4` strips the common prefix from glob paths, so files restore to the wrong location). ## Changes ### Turbo SCM support - New `turbo-scm-base` input on both `frontend-pr-workflow` and `frontend-deploy-workflow` - Sets `TURBO_SCM_BASE` env var on all build/test/deploy steps, enabling Turbo's `--affected` flag ### Monorepo artifact handling - New `build-artifact-path` input — glob pattern for `upload-artifact` (e.g. `apps/*/dist`) to capture builds from all apps. Falls back to `build-output-dir` for single-app repos. - New `build-artifact-download-path` input — directory to extract artifacts into. Needed because `upload-artifact@v4` strips the least common ancestor from glob paths (e.g. `apps/*/dist` uploads as `insights/dist/`, `dashboards/dist/`). Setting this to `apps` restores the correct `apps/*/dist/` structure so deploy tools (`jarvis deploy --path dist`) work from each app's directory.
1 parent a6fe9f6 commit 2d7df61

3 files changed

Lines changed: 84 additions & 6 deletions

File tree

.github/workflows/frontend-deploy-workflow.yml

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,26 @@ on:
5757
description: 'Clean command before build'
5858
type: string
5959
default: 'yarn clean'
60+
# Monorepo artifact handling:
61+
# - build-output-dir: relative path used by deploy tools (e.g. jarvis deploy --path dist)
62+
# from each app's directory. Single-app repos only need this one.
63+
# - build-artifact-path: glob for upload-artifact to capture all app builds
64+
# (e.g. apps/*/dist). Defaults to build-output-dir when not set.
65+
# - build-artifact-download-path: extraction dir — upload-artifact strips the
66+
# common prefix (e.g. apps/) from the glob, so we download into that prefix
67+
# to restore the correct directory structure. Defaults to build-output-dir.
6068
build-output-dir:
6169
description: 'Build output directory name (dist, build, lib, etc.)'
6270
type: string
6371
default: 'dist'
72+
build-artifact-path:
73+
description: 'Path pattern for build artifacts upload (supports globs for monorepos, e.g. apps/*/dist). Defaults to build-output-dir.'
74+
type: string
75+
default: ''
76+
build-artifact-download-path:
77+
description: 'Directory to download build artifacts into. For monorepos where upload-artifact strips the common prefix (e.g. apps/), set this to that prefix. Defaults to build-output-dir.'
78+
type: string
79+
default: ''
6480

6581
# Deploy configuration
6682
deploy-command:
@@ -206,6 +222,12 @@ on:
206222
type: boolean
207223
default: true
208224

225+
# Turbo monorepo configuration
226+
turbo-scm-base:
227+
description: 'Git SHA for Turbo SCM base comparison (enables --affected flag for Turbo monorepos)'
228+
type: string
229+
default: ''
230+
209231
# Timeout configuration
210232
build-timeout:
211233
description: 'Build job timeout (minutes)'
@@ -299,6 +321,7 @@ jobs:
299321
run: ${{ inputs.pre-build-command }}
300322
env:
301323
GH_TOKEN: ${{ secrets.GH_TOKEN }}
324+
TURBO_SCM_BASE: ${{ inputs.turbo-scm-base }}
302325

303326
- name: Clean dist directory
304327
run: ${{ inputs.clean-command }}
@@ -308,6 +331,7 @@ jobs:
308331
env:
309332
PUBLIC_CDN_URL: ${{ inputs.cdn-url }}
310333
GH_TOKEN: ${{ secrets.GH_TOKEN }}
334+
TURBO_SCM_BASE: ${{ inputs.turbo-scm-base }}
311335
JARVIS_DATADOG_LOGS_ENABLED: ${{ inputs.jarvis-datadog-enabled }}
312336
JARVIS_DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY || secrets.DATADOG_API_KEY_FRONTEND_METRICS }}
313337
JARVIS_DATADOG_SITE: datadoghq.com
@@ -326,7 +350,7 @@ jobs:
326350
uses: actions/upload-artifact@v4
327351
with:
328352
name: build-${{ github.run_id }}
329-
path: ${{ inputs.build-output-dir }}
353+
path: ${{ inputs.build-artifact-path || inputs.build-output-dir }}
330354
retention-days: 1
331355

332356
# Job 2: Unit Tests (runs in parallel with other tests)
@@ -363,11 +387,13 @@ jobs:
363387
run: ${{ inputs.pre-test-command }}
364388
env:
365389
GH_TOKEN: ${{ secrets.GH_TOKEN }}
390+
TURBO_SCM_BASE: ${{ inputs.turbo-scm-base }}
366391

367392
- name: Run unit tests
368393
run: ${{ inputs.unit-test-command }}
369394
env:
370395
GH_TOKEN: ${{ secrets.GH_TOKEN }}
396+
TURBO_SCM_BASE: ${{ inputs.turbo-scm-base }}
371397

372398
- name: Upload coverage
373399
if: always()
@@ -413,17 +439,19 @@ jobs:
413439
run: ${{ inputs.pre-test-command }}
414440
env:
415441
GH_TOKEN: ${{ secrets.GH_TOKEN }}
442+
TURBO_SCM_BASE: ${{ inputs.turbo-scm-base }}
416443

417444
- name: Download Build Artifacts
418445
uses: Typeform/.github/shared-actions/download-build-artifacts@v1
419446
with:
420447
artifact-name: ${{ needs.build.outputs.artifact-name }}
421-
output-dir: ${{ inputs.build-output-dir }}
448+
output-dir: ${{ inputs.build-artifact-download-path || inputs.build-output-dir }}
422449

423450
- name: Run integration tests
424451
run: ${{ inputs.integration-test-command }}
425452
env:
426453
GH_TOKEN: ${{ secrets.GH_TOKEN }}
454+
TURBO_SCM_BASE: ${{ inputs.turbo-scm-base }}
427455

428456
- name: Upload test results
429457
if: always()
@@ -555,7 +583,7 @@ jobs:
555583
uses: Typeform/.github/shared-actions/download-build-artifacts@v1
556584
with:
557585
artifact-name: ${{ needs.build.outputs.artifact-name }}
558-
output-dir: ${{ inputs.build-output-dir }}
586+
output-dir: ${{ inputs.build-artifact-download-path || inputs.build-output-dir }}
559587

560588
- name: Setup Jarvis
561589
uses: Typeform/.github/shared-actions/setup-jarvis@v1
@@ -577,6 +605,7 @@ jobs:
577605
DEBUG: jarvis
578606
# GitHub
579607
GH_TOKEN: ${{ secrets.GH_TOKEN }}
608+
TURBO_SCM_BASE: ${{ inputs.turbo-scm-base }}
580609
# AWS configuration
581610
AWS_REGION: ${{ inputs.aws-region }}
582611
AWS_ASSETS_BUCKET: ${{ inputs.cdn-bucket }}

.github/workflows/frontend-pr-workflow.yml

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,26 @@ on:
183183
description: 'Deploy command'
184184
type: string
185185
default: 'yarn deploy:preview'
186+
# Monorepo artifact handling:
187+
# - build-output-dir: relative path used by deploy tools (e.g. jarvis deploy --path dist)
188+
# from each app's directory. Single-app repos only need this one.
189+
# - build-artifact-path: glob for upload-artifact to capture all app builds
190+
# (e.g. apps/*/dist). Defaults to build-output-dir when not set.
191+
# - build-artifact-download-path: extraction dir — upload-artifact strips the
192+
# common prefix (e.g. apps/) from the glob, so we download into that prefix
193+
# to restore the correct directory structure. Defaults to build-output-dir.
186194
build-output-dir:
187195
description: 'Build output directory name (dist, build, lib, etc.)'
188196
type: string
189197
default: 'dist'
198+
build-artifact-path:
199+
description: 'Path pattern for build artifacts upload (supports globs for monorepos, e.g. apps/*/dist). Defaults to build-output-dir.'
200+
type: string
201+
default: ''
202+
build-artifact-download-path:
203+
description: 'Directory to download build artifacts into. For monorepos where upload-artifact strips the common prefix (e.g. apps/), set this to that prefix. Defaults to build-output-dir.'
204+
type: string
205+
default: ''
190206
cdn-bucket:
191207
description: 'S3 bucket for assets'
192208
type: string
@@ -218,6 +234,12 @@ on:
218234
type: string
219235
default: 'staging'
220236

237+
# Turbo monorepo configuration
238+
turbo-scm-base:
239+
description: 'Git SHA for Turbo SCM base comparison (enables --affected flag for Turbo monorepos)'
240+
type: string
241+
default: ''
242+
221243
# Timeout configuration
222244
build-timeout:
223245
description: 'Build job timeout (minutes)'
@@ -304,10 +326,13 @@ jobs:
304326
run: ${{ inputs.pre-build-command }}
305327
env:
306328
GH_TOKEN: ${{ secrets.GH_TOKEN }}
329+
TURBO_SCM_BASE: ${{ inputs.turbo-scm-base }}
307330

308331
- name: Run linting
309332
if: inputs.run-linting
310333
run: ${{ inputs.lint-command }}
334+
env:
335+
TURBO_SCM_BASE: ${{ inputs.turbo-scm-base }}
311336

312337
- name: Clean dist directory
313338
run: ${{ inputs.clean-command }}
@@ -317,6 +342,7 @@ jobs:
317342
env:
318343
PUBLIC_CDN_URL: ${{ inputs.cdn-url }}
319344
GH_TOKEN: ${{ secrets.GH_TOKEN }}
345+
TURBO_SCM_BASE: ${{ inputs.turbo-scm-base }}
320346
JARVIS_DATADOG_LOGS_ENABLED: ${{ inputs.jarvis-datadog-enabled }}
321347
JARVIS_DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY || secrets.DATADOG_API_KEY_FRONTEND_METRICS }}
322348
JARVIS_DATADOG_SITE: datadoghq.com
@@ -336,7 +362,7 @@ jobs:
336362
uses: actions/upload-artifact@v4
337363
with:
338364
name: build-${{ github.run_id }}
339-
path: ${{ inputs.build-output-dir }}
365+
path: ${{ inputs.build-artifact-path || inputs.build-output-dir }}
340366
retention-days: 1
341367

342368
# Job 2: Unit Tests (parallel with integration tests)
@@ -371,11 +397,13 @@ jobs:
371397
run: ${{ inputs.pre-test-command }}
372398
env:
373399
GH_TOKEN: ${{ secrets.GH_TOKEN }}
400+
TURBO_SCM_BASE: ${{ inputs.turbo-scm-base }}
374401

375402
- name: Run unit tests
376403
run: ${{ inputs.unit-test-command }}
377404
env:
378405
GH_TOKEN: ${{ secrets.GH_TOKEN }}
406+
TURBO_SCM_BASE: ${{ inputs.turbo-scm-base }}
379407

380408
- name: Upload coverage
381409
if: always()
@@ -417,6 +445,7 @@ jobs:
417445
run: ${{ inputs.pre-test-command }}
418446
env:
419447
GH_TOKEN: ${{ secrets.GH_TOKEN }}
448+
TURBO_SCM_BASE: ${{ inputs.turbo-scm-base }}
420449

421450
- name: Setup Playwright
422451
if: inputs.integration-test-framework == 'playwright'
@@ -426,12 +455,13 @@ jobs:
426455
uses: Typeform/.github/shared-actions/download-build-artifacts@v1
427456
with:
428457
artifact-name: ${{ needs.build.outputs.artifact-name }}
429-
output-dir: ${{ inputs.build-output-dir }}
458+
output-dir: ${{ inputs.build-artifact-download-path || inputs.build-output-dir }}
430459

431460
- name: Run integration tests
432461
run: ${{ inputs.integration-test-command }}
433462
env:
434463
GH_TOKEN: ${{ secrets.GH_TOKEN }}
464+
TURBO_SCM_BASE: ${{ inputs.turbo-scm-base }}
435465

436466
- name: Upload test results
437467
if: always()
@@ -469,7 +499,7 @@ jobs:
469499
uses: Typeform/.github/shared-actions/download-build-artifacts@v1
470500
with:
471501
artifact-name: ${{ needs.build.outputs.artifact-name }}
472-
output-dir: ${{ inputs.build-output-dir }}
502+
output-dir: ${{ inputs.build-artifact-download-path || inputs.build-output-dir }}
473503

474504
- name: Setup Jarvis
475505
uses: Typeform/.github/shared-actions/setup-jarvis@v1
@@ -489,6 +519,7 @@ jobs:
489519
env:
490520
DEBUG: jarvis
491521
GH_TOKEN: ${{ secrets.GH_TOKEN }}
522+
TURBO_SCM_BASE: ${{ inputs.turbo-scm-base }}
492523
AWS_ASSETS_BUCKET: ${{ inputs.cdn-bucket }}
493524
AWS_CLOUDFRONT_DIST: ${{ inputs.cloudfront-dist }}
494525
PUBLIC_CDN_URL: ${{ inputs.cdn-url }}

reusable-workflows/frontend-pr-workflow/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ jobs:
6767
| `run-deep-purple` | Run Deep Purple E2E tests | `false` |
6868
| `deploy-preview` | Deploy preview environment | `true` |
6969
| `deploy-command` | Deploy command | `'yarn deploy:preview'` |
70+
| `turbo-scm-base` | Git SHA for Turbo SCM base comparison (enables `--affected` flag for Turbo monorepos). Sets `TURBO_SCM_BASE` env var on all command steps. | `''` |
7071
| `jarvis-branch` | Jarvis branch to use | `''` |
7172
| `jarvis-datadog-enabled` | Enable Jarvis Datadog logging | `true` |
7273
| `jarvis-datadog-env` | Datadog environment | `'staging'` |
@@ -277,6 +278,22 @@ with:
277278
run-unit-tests: true
278279
```
279280
281+
### performance-analytics (Turbo monorepo with --affected)
282+
```yaml
283+
with:
284+
app-name: 'performance-analytics'
285+
use-asdf: true
286+
cache-mode: 'full'
287+
turbo-scm-base: ${{ github.event.pull_request.base.sha }}
288+
pre-build-command: 'echo "GRAPHQL_SCHEMA_URL=${{ vars.GRAPHQL_SCHEMA_URL }}" >> $GITHUB_ENV'
289+
build-command: 'yarn dist:preview --affected'
290+
run-unit-tests: true
291+
unit-test-command: 'yarn verify --affected --concurrency=1'
292+
run-integration-tests: true
293+
integration-test-command: 'yarn test:integration --affected && yarn test:visual --affected'
294+
run-deep-purple: false # Handled separately via matrix job
295+
```
296+
280297
### hall-of-forms
281298
```yaml
282299
with:
@@ -384,6 +401,7 @@ git push origin main
384401
- ✅ hall-of-forms
385402
- ✅ bob-the-builder
386403
- ✅ chief
404+
- ✅ performance-analytics (Turbo monorepo with `turbo-scm-base`)
387405

388406
**All frontend applications**
389407

0 commit comments

Comments
 (0)