Skip to content

Commit 4b6680a

Browse files
authored
Merge pull request #36 from tokenhost/feat/generated-app-ci-template-v2
Generated app CI: emit default workflow template for app-level tests
2 parents c3f5fe8 + 1d1a8ff commit 4b6680a

4 files changed

Lines changed: 129 additions & 0 deletions

File tree

docs/generated-app-ci.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Generated App CI
2+
3+
When you run `th generate <schema> --with-tests`, the generated UI app includes:
4+
5+
- `tests/contract/integration.mjs`
6+
- `tests/ui/smoke.mjs`
7+
- `.github/workflows/generated-app-ci.yml`
8+
9+
The emitted workflow runs in GitHub Actions and is designed to work in a generated app repository with no manual CI authoring.
10+
11+
## Default workflow behavior
12+
13+
- Uses Node 20 and pnpm.
14+
- Caches pnpm store using a lockfile-based key.
15+
- Installs dependencies with `pnpm install --frozen-lockfile`.
16+
- Installs Foundry/anvil.
17+
- Runs generated contract tests with `pnpm run test:contract`.
18+
- Runs generated UI tests with `pnpm run test:ui`.
19+
20+
## Optional workflow knobs
21+
22+
Use repository or environment variables to tune runtime cost:
23+
24+
- `TH_SKIP_CONTRACT_TESTS=1`
25+
- Skip Foundry installation and contract tests.
26+
- `TH_SKIP_UI_TESTS=1`
27+
- Skip UI smoke tests.
28+
- `TH_INSTALL_BROWSER_DEPS=1`
29+
- Install Playwright Chromium dependencies when Playwright exists in the generated app.
30+
31+
## Canonical app validation in this builder repo
32+
33+
This repo validates generated-app test scaffolds and canonical job-board behavior through integration tests under `test/integration/`:
34+
35+
- generated contract scaffold execution
36+
- generated UI scaffold execution against live preview
37+
- end-to-end canonical job-board flow
38+
39+
These checks back the required `integration-local` CI job in this repository.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: Generated App CI
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- master
8+
pull_request:
9+
10+
jobs:
11+
generated-app-tests:
12+
runs-on: ubuntu-latest
13+
timeout-minutes: 25
14+
env:
15+
NEXT_TELEMETRY_DISABLED: '1'
16+
steps:
17+
- name: Checkout
18+
uses: actions/checkout@v4
19+
20+
- name: Setup Node
21+
uses: actions/setup-node@v4
22+
with:
23+
node-version: '20'
24+
25+
- name: Setup pnpm
26+
uses: pnpm/action-setup@v4
27+
with:
28+
version: '10.12.1'
29+
30+
- name: Get pnpm store path
31+
id: pnpm-store
32+
shell: bash
33+
run: echo "store_path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
34+
35+
- name: Cache pnpm store
36+
uses: actions/cache@v4
37+
with:
38+
path: ${{ steps.pnpm-store.outputs.store_path }}
39+
key: generated-app-pnpm-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
40+
restore-keys: |
41+
generated-app-pnpm-${{ runner.os }}-
42+
43+
- name: Install dependencies
44+
run: pnpm install --frozen-lockfile
45+
46+
- name: Install Foundry (anvil)
47+
if: ${{ env.TH_SKIP_CONTRACT_TESTS != '1' }}
48+
uses: foundry-rs/foundry-toolchain@v1
49+
with:
50+
version: stable
51+
52+
- name: Confirm anvil
53+
if: ${{ env.TH_SKIP_CONTRACT_TESTS != '1' }}
54+
run: anvil --version
55+
56+
- name: Install browser deps (optional)
57+
if: ${{ env.TH_INSTALL_BROWSER_DEPS == '1' }}
58+
run: |
59+
if pnpm exec playwright --version >/dev/null 2>&1; then
60+
pnpm exec playwright install --with-deps chromium
61+
else
62+
echo "Playwright is not installed; skipping browser dependency install."
63+
fi
64+
65+
- name: Run generated contract tests
66+
if: ${{ env.TH_SKIP_CONTRACT_TESTS != '1' }}
67+
run: pnpm run test:contract
68+
69+
- name: Run generated UI tests
70+
if: ${{ env.TH_SKIP_UI_TESTS != '1' }}
71+
run: pnpm run test:ui

packages/templates/next-export-ui/test-scaffold/tests/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
Generated app test scaffold
22

33
This directory is emitted by `th generate --with-tests`.
4+
The same scaffold also emits `.github/workflows/generated-app-ci.yml`.
45

56
- `contract/integration.mjs` runs schema-driven contract behavior tests against local anvil.
67
- `contract/smoke.mjs` validates baseline generated app contract test preconditions.
@@ -19,4 +20,14 @@ UI smoke test env vars:
1920

2021
When `TH_UI_BASE_URL` is not set, `ui/smoke.mjs` runs static scaffold checks only.
2122

23+
Generated CI workflow defaults:
24+
- Install dependencies with pnpm on Node 20.
25+
- Install Foundry/anvil and run `pnpm run test:contract`.
26+
- Run `pnpm run test:ui`.
27+
28+
Generated CI workflow knobs:
29+
- `TH_SKIP_CONTRACT_TESTS=1` skips Foundry install and contract tests.
30+
- `TH_SKIP_UI_TESTS=1` skips UI tests.
31+
- `TH_INSTALL_BROWSER_DEPS=1` installs Playwright Chromium deps if Playwright is present.
32+
2233
These tests are schema-driven and intended to be expanded further for app-specific assertions.

test/testCliGenerateUi.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ describe('th generate (UI template)', function () {
125125
expect(fs.existsSync(path.join(uiDir, 'tests', 'contract', 'smoke.mjs'))).to.equal(true);
126126
expect(fs.existsSync(path.join(uiDir, 'tests', 'contract', 'integration.mjs'))).to.equal(true);
127127
expect(fs.existsSync(path.join(uiDir, 'tests', 'ui', 'smoke.mjs'))).to.equal(true);
128+
expect(fs.existsSync(path.join(uiDir, '.github', 'workflows', 'generated-app-ci.yml'))).to.equal(true);
128129

129130
const pkg = JSON.parse(fs.readFileSync(path.join(uiDir, 'package.json'), 'utf-8'));
130131
expect(pkg?.scripts?.test).to.equal('pnpm run test:contract && pnpm run test:ui');
@@ -138,5 +139,12 @@ describe('th generate (UI template)', function () {
138139

139140
const uiSmoke = runCmd('node', ['tests/ui/smoke.mjs'], uiDir);
140141
expect(uiSmoke.status, uiSmoke.stderr || uiSmoke.stdout).to.equal(0);
142+
143+
const workflow = fs.readFileSync(path.join(uiDir, '.github', 'workflows', 'generated-app-ci.yml'), 'utf-8');
144+
expect(workflow).to.include('pnpm run test:contract');
145+
expect(workflow).to.include('pnpm run test:ui');
146+
expect(workflow).to.include('TH_SKIP_CONTRACT_TESTS');
147+
expect(workflow).to.include('TH_SKIP_UI_TESTS');
148+
expect(workflow).to.include('TH_INSTALL_BROWSER_DEPS');
141149
});
142150
});

0 commit comments

Comments
 (0)