Skip to content

Commit f313e97

Browse files
committed
fix(ci): split full integration preflight
1 parent f24d93f commit f313e97

3 files changed

Lines changed: 139 additions & 17 deletions

File tree

.github/workflows/integration-full.yml

Lines changed: 76 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ on:
99
default: false
1010
type: boolean
1111
only:
12-
description: Optional scenario filter
12+
description: Optional scenario filter (smoke or full)
1313
required: false
14+
default: ""
1415
type: string
1516
workflow_call:
1617
inputs:
@@ -66,13 +67,13 @@ permissions:
6667
contents: read
6768

6869
jobs:
69-
full:
70+
smoke:
71+
name: smoke
7072
runs-on: ubuntu-24.04
71-
timeout-minutes: 480
73+
timeout-minutes: 240
74+
if: ${{ inputs.only == '' || inputs.only == 'smoke' }}
7275
concurrency:
73-
# Shared with integration-smoke. Release preflight takes priority over an
74-
# already-running smoke run for the same release candidate.
75-
group: terrarium-integration
76+
group: terrarium-integration-${{ github.workflow }}-${{ github.ref }}-smoke
7677
cancel-in-progress: ${{ inputs.release_preflight == true }}
7778
env:
7879
HCLOUD_TOKEN: ${{ secrets.HCLOUD_TOKEN }}
@@ -92,10 +93,10 @@ jobs:
9293
CIFS_USERNAME: ${{ secrets.CIFS_USERNAME }}
9394
CIFS_PASSWORD: ${{ secrets.CIFS_PASSWORD }}
9495
CIFS_HOST_PATH_BASE: ${{ secrets.CIFS_HOST_PATH_BASE }}
95-
TERRARIUM_INTEGRATION_OUTPUT_DIR: ${{ github.workspace }}/tests/integration/output
96+
TERRARIUM_INTEGRATION_SLUG: gha-${{ github.run_id }}-${{ github.run_attempt }}-smoke
97+
TERRARIUM_INTEGRATION_OUTPUT_DIR: ${{ github.workspace }}/tests/integration/output/smoke
9698
KEEP_ON_FAILURE: ${{ inputs.keep_on_failure && 'true' || 'false' }}
9799
RELEASE_PREFLIGHT: ${{ inputs.release_preflight && 'true' || 'false' }}
98-
ONLY_SCENARIO: ${{ inputs.only }}
99100
steps:
100101
- uses: actions/checkout@v4
101102
- uses: oven-sh/setup-bun@v2
@@ -105,12 +106,73 @@ jobs:
105106
sudo apt-get install -y openssh-client tar
106107
bun install --frozen-lockfile
107108
bunx playwright install --with-deps chromium
108-
- name: Run full suite
109+
- name: Generate integration SSH key
110+
run: |
111+
ssh-keygen -t ed25519 -N "" -C "terrarium-${TERRARIUM_INTEGRATION_SLUG}" -f "${RUNNER_TEMP}/terrarium-integration-id_ed25519"
112+
chmod 600 "${RUNNER_TEMP}/terrarium-integration-id_ed25519"
113+
{
114+
echo "HCLOUD_SSH_PRIVATE_KEY_FILE=${RUNNER_TEMP}/terrarium-integration-id_ed25519"
115+
echo "HCLOUD_SSH_PUBLIC_KEY_FILE=${RUNNER_TEMP}/terrarium-integration-id_ed25519.pub"
116+
} >> "${GITHUB_ENV}"
117+
- name: Run smoke suite
118+
run: |
119+
if [ "${RELEASE_PREFLIGHT}" = "true" ]; then
120+
bun run tests/integration/index.ts --suite smoke --release-preflight
121+
else
122+
bun run tests/integration/index.ts --suite smoke
123+
fi
124+
125+
post_smoke:
126+
name: post-smoke
127+
runs-on: ubuntu-24.04
128+
timeout-minutes: 360
129+
if: ${{ inputs.only == '' || inputs.only == 'full' }}
130+
concurrency:
131+
group: terrarium-integration-${{ github.workflow }}-${{ github.ref }}-post-smoke
132+
cancel-in-progress: ${{ inputs.release_preflight == true }}
133+
env:
134+
HCLOUD_TOKEN: ${{ secrets.HCLOUD_TOKEN }}
135+
HCLOUD_LOCATION: ${{ secrets.HCLOUD_LOCATION }}
136+
HCLOUD_SERVER_TYPE: ${{ secrets.HCLOUD_SERVER_TYPE }}
137+
HCLOUD_SSH_PRIVATE_KEY: ${{ secrets.HCLOUD_SSH_PRIVATE_KEY }}
138+
HCLOUD_SSH_PUBLIC_KEY: ${{ secrets.HCLOUD_SSH_PUBLIC_KEY }}
139+
ZITADEL_CLOUD_ISSUER: ${{ secrets.ZITADEL_CLOUD_ISSUER }}
140+
ZITADEL_CLOUD_PAT: ${{ secrets.ZITADEL_CLOUD_PAT }}
141+
ZITADEL_CLOUD_ORG_ID: ${{ secrets.ZITADEL_CLOUD_ORG_ID }}
142+
S3_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
143+
S3_BUCKET: ${{ secrets.S3_BUCKET }}
144+
S3_REGION: ${{ secrets.S3_REGION }}
145+
S3_ACCESS_KEY: ${{ secrets.S3_ACCESS_KEY }}
146+
S3_SECRET_KEY: ${{ secrets.S3_SECRET_KEY }}
147+
CIFS_ADDRESS: ${{ secrets.CIFS_ADDRESS }}
148+
CIFS_USERNAME: ${{ secrets.CIFS_USERNAME }}
149+
CIFS_PASSWORD: ${{ secrets.CIFS_PASSWORD }}
150+
CIFS_HOST_PATH_BASE: ${{ secrets.CIFS_HOST_PATH_BASE }}
151+
TERRARIUM_INTEGRATION_SLUG: gha-${{ github.run_id }}-${{ github.run_attempt }}-post-smoke
152+
TERRARIUM_INTEGRATION_OUTPUT_DIR: ${{ github.workspace }}/tests/integration/output/post-smoke
153+
KEEP_ON_FAILURE: ${{ inputs.keep_on_failure && 'true' || 'false' }}
154+
RELEASE_PREFLIGHT: ${{ inputs.release_preflight && 'true' || 'false' }}
155+
steps:
156+
- uses: actions/checkout@v4
157+
- uses: oven-sh/setup-bun@v2
158+
- name: Install integration dependencies
159+
run: |
160+
sudo apt-get update
161+
sudo apt-get install -y openssh-client tar
162+
bun install --frozen-lockfile
163+
bunx playwright install --with-deps chromium
164+
- name: Generate integration SSH key
165+
run: |
166+
ssh-keygen -t ed25519 -N "" -C "terrarium-${TERRARIUM_INTEGRATION_SLUG}" -f "${RUNNER_TEMP}/terrarium-integration-id_ed25519"
167+
chmod 600 "${RUNNER_TEMP}/terrarium-integration-id_ed25519"
168+
{
169+
echo "HCLOUD_SSH_PRIVATE_KEY_FILE=${RUNNER_TEMP}/terrarium-integration-id_ed25519"
170+
echo "HCLOUD_SSH_PUBLIC_KEY_FILE=${RUNNER_TEMP}/terrarium-integration-id_ed25519.pub"
171+
} >> "${GITHUB_ENV}"
172+
- name: Run post-smoke suite
109173
run: |
110-
if [ -n "${ONLY_SCENARIO}" ]; then
111-
bun run tests/integration/index.ts --suite full --release-preflight --only "${ONLY_SCENARIO}"
112-
elif [ "${RELEASE_PREFLIGHT}" = "true" ]; then
113-
bun run tests/integration/index.ts --suite full --release-preflight
174+
if [ "${RELEASE_PREFLIGHT}" = "true" ]; then
175+
bun run tests/integration/index.ts --suite full --release-preflight --only full
114176
else
115-
bun run tests/integration/index.ts --suite full
177+
bun run tests/integration/index.ts --suite full --only full
116178
fi

.github/workflows/integration-smoke.yml

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ jobs:
2121
runs-on: ubuntu-24.04
2222
timeout-minutes: 240
2323
concurrency:
24-
# Shared with integration-full so Hetzner-backed integration suites do not run at the same time.
25-
group: terrarium-integration
24+
group: terrarium-integration-${{ github.workflow }}-${{ github.ref }}-smoke
2625
cancel-in-progress: false
2726
env:
2827
HCLOUD_TOKEN: ${{ secrets.HCLOUD_TOKEN }}
@@ -42,7 +41,8 @@ jobs:
4241
CIFS_USERNAME: ${{ secrets.CIFS_USERNAME }}
4342
CIFS_PASSWORD: ${{ secrets.CIFS_PASSWORD }}
4443
CIFS_HOST_PATH_BASE: ${{ secrets.CIFS_HOST_PATH_BASE }}
45-
TERRARIUM_INTEGRATION_OUTPUT_DIR: ${{ github.workspace }}/tests/integration/output
44+
TERRARIUM_INTEGRATION_SLUG: gha-${{ github.run_id }}-${{ github.run_attempt }}-smoke
45+
TERRARIUM_INTEGRATION_OUTPUT_DIR: ${{ github.workspace }}/tests/integration/output/smoke
4646
KEEP_ON_FAILURE: ${{ inputs.keep_on_failure && 'true' || 'false' }}
4747
ONLY_SCENARIO: ${{ inputs.only }}
4848
steps:
@@ -54,6 +54,14 @@ jobs:
5454
sudo apt-get install -y openssh-client tar
5555
bun install --frozen-lockfile
5656
bunx playwright install --with-deps chromium
57+
- name: Generate integration SSH key
58+
run: |
59+
ssh-keygen -t ed25519 -N "" -C "terrarium-${TERRARIUM_INTEGRATION_SLUG}" -f "${RUNNER_TEMP}/terrarium-integration-id_ed25519"
60+
chmod 600 "${RUNNER_TEMP}/terrarium-integration-id_ed25519"
61+
{
62+
echo "HCLOUD_SSH_PRIVATE_KEY_FILE=${RUNNER_TEMP}/terrarium-integration-id_ed25519"
63+
echo "HCLOUD_SSH_PUBLIC_KEY_FILE=${RUNNER_TEMP}/terrarium-integration-id_ed25519.pub"
64+
} >> "${GITHUB_ENV}"
5765
- name: Run smoke suite
5866
run: |
5967
if [ -n "${ONLY_SCENARIO}" ]; then

tests/integration-workflow.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { describe, expect, test } from "bun:test";
2+
import { readFileSync } from "node:fs";
3+
import { join } from "node:path";
4+
import YAML from "yaml";
5+
6+
const repoRoot = join(import.meta.dir, "..");
7+
8+
function workflow(name: string): Record<string, any> {
9+
return YAML.parse(readFileSync(join(repoRoot, ".github/workflows", name), "utf8"));
10+
}
11+
12+
describe("integration workflows", () => {
13+
test("full integration runs smoke and post-smoke as independent slices", () => {
14+
const full = workflow("integration-full.yml");
15+
const smoke = full.jobs.smoke;
16+
const postSmoke = full.jobs.post_smoke;
17+
18+
expect(smoke).toBeDefined();
19+
expect(postSmoke).toBeDefined();
20+
expect(smoke.needs).toBeUndefined();
21+
expect(postSmoke.needs).toBeUndefined();
22+
expect(smoke.if).toBe("${{ inputs.only == '' || inputs.only == 'smoke' }}");
23+
expect(postSmoke.if).toBe("${{ inputs.only == '' || inputs.only == 'full' }}");
24+
expect(smoke.steps.at(-1).run).toContain("bun run tests/integration/index.ts --suite smoke");
25+
expect(postSmoke.steps.at(-1).run).toContain("bun run tests/integration/index.ts --suite full --only full");
26+
});
27+
28+
test("parallel integration slices use isolated resources and SSH keys", () => {
29+
const full = workflow("integration-full.yml");
30+
const standaloneSmoke = workflow("integration-smoke.yml");
31+
const fullSmoke = full.jobs.smoke;
32+
const postSmoke = full.jobs.post_smoke;
33+
const smoke = standaloneSmoke.jobs.smoke;
34+
35+
expect(fullSmoke.env.TERRARIUM_INTEGRATION_SLUG).toBe("gha-${{ github.run_id }}-${{ github.run_attempt }}-smoke");
36+
expect(postSmoke.env.TERRARIUM_INTEGRATION_SLUG).toBe("gha-${{ github.run_id }}-${{ github.run_attempt }}-post-smoke");
37+
expect(fullSmoke.env.TERRARIUM_INTEGRATION_OUTPUT_DIR).toBe("${{ github.workspace }}/tests/integration/output/smoke");
38+
expect(postSmoke.env.TERRARIUM_INTEGRATION_OUTPUT_DIR).toBe("${{ github.workspace }}/tests/integration/output/post-smoke");
39+
expect(fullSmoke.concurrency.group).toBe("terrarium-integration-${{ github.workflow }}-${{ github.ref }}-smoke");
40+
expect(postSmoke.concurrency.group).toBe("terrarium-integration-${{ github.workflow }}-${{ github.ref }}-post-smoke");
41+
42+
expect(smoke.env.TERRARIUM_INTEGRATION_SLUG).toBe("gha-${{ github.run_id }}-${{ github.run_attempt }}-smoke");
43+
expect(smoke.concurrency.group).toBe("terrarium-integration-${{ github.workflow }}-${{ github.ref }}-smoke");
44+
45+
for (const job of [fullSmoke, postSmoke, smoke]) {
46+
const keygenStep = job.steps.find((step: { name?: string }) => step.name === "Generate integration SSH key");
47+
expect(keygenStep?.run).toContain("ssh-keygen -t ed25519");
48+
expect(keygenStep?.run).toContain("HCLOUD_SSH_PRIVATE_KEY_FILE=");
49+
expect(keygenStep?.run).toContain("HCLOUD_SSH_PUBLIC_KEY_FILE=");
50+
}
51+
});
52+
});

0 commit comments

Comments
 (0)