Skip to content

Commit 769508d

Browse files
committed
perf(ci): gate install smoke on changed-smoke
1 parent b369397 commit 769508d

File tree

6 files changed

+100
-4
lines changed

6 files changed

+100
-4
lines changed

.github/workflows/install-smoke.yml

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,42 @@ jobs:
3737
id: check
3838
uses: ./.github/actions/detect-docs-changes
3939

40-
install-smoke:
40+
changed-smoke:
4141
needs: [docs-scope]
42-
if: (github.event_name != 'pull_request' || !github.event.pull_request.draft) && needs.docs-scope.outputs.docs_only != 'true'
42+
if: needs.docs-scope.outputs.docs_only != 'true'
43+
runs-on: blacksmith-16vcpu-ubuntu-2404
44+
outputs:
45+
run_changed_smoke: ${{ steps.scope.outputs.run_changed_smoke }}
46+
steps:
47+
- name: Checkout
48+
uses: actions/checkout@v6
49+
with:
50+
fetch-depth: 1
51+
fetch-tags: false
52+
53+
- name: Ensure changed-smoke base commit
54+
uses: ./.github/actions/ensure-base-commit
55+
with:
56+
base-sha: ${{ github.event_name == 'push' && github.event.before || github.event.pull_request.base.sha }}
57+
fetch-ref: ${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.base.ref }}
58+
59+
- name: Detect changed smoke scope
60+
id: scope
61+
shell: bash
62+
run: |
63+
set -euo pipefail
64+
65+
if [ "${{ github.event_name }}" = "push" ]; then
66+
BASE="${{ github.event.before }}"
67+
else
68+
BASE="${{ github.event.pull_request.base.sha }}"
69+
fi
70+
71+
node scripts/ci-changed-scope.mjs --base "$BASE" --head HEAD
72+
73+
install-smoke:
74+
needs: [docs-scope, changed-smoke]
75+
if: (github.event_name != 'pull_request' || !github.event.pull_request.draft) && needs.docs-scope.outputs.docs_only != 'true' && needs.changed-smoke.outputs.run_changed_smoke == 'true'
4376
runs-on: blacksmith-16vcpu-ubuntu-2404
4477
env:
4578
DOCKER_BUILD_SUMMARY: "false"

docs/ci.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Jobs are ordered so cheap checks fail before expensive ones run:
3636
3. Pushes to `main`: `build-artifacts` + `release-check` + Bun compat + `compat-node22`
3737

3838
Scope logic lives in `scripts/ci-changed-scope.mjs` and is covered by unit tests in `src/scripts/ci-changed-scope.test.ts`.
39+
The same shared scope module also drives the separate `install-smoke` workflow through a narrower `changed-smoke` gate, so Docker/install smoke only runs for install, packaging, and container-relevant changes.
3940

4041
## Runners
4142

scripts/ci-changed-scope.d.mts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ export type ChangedScope = {
22
runNode: boolean;
33
runMacos: boolean;
44
runAndroid: boolean;
5+
runWindows: boolean;
6+
runSkillsPython: boolean;
7+
runChangedSmoke: boolean;
58
};
69

710
export function detectChangedScope(changedPaths: string[]): ChangedScope;

scripts/ci-changed-scope.mjs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { execFileSync } from "node:child_process";
22
import { appendFileSync } from "node:fs";
33

4-
/** @typedef {{ runNode: boolean; runMacos: boolean; runAndroid: boolean; runWindows: boolean; runSkillsPython: boolean }} ChangedScope */
4+
/** @typedef {{ runNode: boolean; runMacos: boolean; runAndroid: boolean; runWindows: boolean; runSkillsPython: boolean; runChangedSmoke: boolean }} ChangedScope */
55

66
const DOCS_PATH_RE = /^(docs\/|.*\.mdx?$)/;
77
const SKILLS_PYTHON_SCOPE_RE = /^(skills\/|pyproject\.toml$)/;
88
const CI_WORKFLOW_SCOPE_RE = /^\.github\/workflows\/ci\.yml$/;
9+
const INSTALL_SMOKE_WORKFLOW_SCOPE_RE = /^\.github\/workflows\/install-smoke\.yml$/;
910
const MACOS_PROTOCOL_GEN_RE =
1011
/^(apps\/macos\/Sources\/OpenClawProtocol\/|apps\/shared\/OpenClawKit\/Sources\/OpenClawProtocol\/)/;
1112
const MACOS_NATIVE_RE = /^(apps\/macos\/|apps\/ios\/|apps\/shared\/|Swabble\/)/;
@@ -16,6 +17,8 @@ const WINDOWS_SCOPE_RE =
1617
/^(src\/|test\/|extensions\/|packages\/|scripts\/|ui\/|openclaw\.mjs$|package\.json$|pnpm-lock\.yaml$|pnpm-workspace\.yaml$|tsconfig.*\.json$|vitest.*\.ts$|tsdown\.config\.ts$|\.github\/workflows\/ci\.yml$|\.github\/actions\/setup-node-env\/action\.yml$|\.github\/actions\/setup-pnpm-store-cache\/action\.yml$)/;
1718
const NATIVE_ONLY_RE =
1819
/^(apps\/android\/|apps\/ios\/|apps\/macos\/|apps\/shared\/|Swabble\/|appcast\.xml$)/;
20+
const CHANGED_SMOKE_SCOPE_RE =
21+
/^(Dockerfile$|\.npmrc$|package\.json$|pnpm-lock\.yaml$|pnpm-workspace\.yaml$|scripts\/install\.sh$|scripts\/test-install-sh-docker\.sh$|scripts\/docker\/|extensions\/[^/]+\/package\.json$|\.github\/workflows\/install-smoke\.yml$|\.github\/actions\/setup-node-env\/action\.yml$)/;
1922

2023
/**
2124
* @param {string[]} changedPaths
@@ -29,6 +32,7 @@ export function detectChangedScope(changedPaths) {
2932
runAndroid: true,
3033
runWindows: true,
3134
runSkillsPython: true,
35+
runChangedSmoke: true,
3236
};
3337
}
3438

@@ -37,6 +41,7 @@ export function detectChangedScope(changedPaths) {
3741
let runAndroid = false;
3842
let runWindows = false;
3943
let runSkillsPython = false;
44+
let runChangedSmoke = false;
4045
let hasNonDocs = false;
4146
let hasNonNativeNonDocs = false;
4247

@@ -62,6 +67,10 @@ export function detectChangedScope(changedPaths) {
6267
runSkillsPython = true;
6368
}
6469

70+
if (INSTALL_SMOKE_WORKFLOW_SCOPE_RE.test(path)) {
71+
runChangedSmoke = true;
72+
}
73+
6574
if (!MACOS_PROTOCOL_GEN_RE.test(path) && MACOS_NATIVE_RE.test(path)) {
6675
runMacos = true;
6776
}
@@ -78,6 +87,10 @@ export function detectChangedScope(changedPaths) {
7887
runWindows = true;
7988
}
8089

90+
if (CHANGED_SMOKE_SCOPE_RE.test(path)) {
91+
runChangedSmoke = true;
92+
}
93+
8194
if (!NATIVE_ONLY_RE.test(path)) {
8295
hasNonNativeNonDocs = true;
8396
}
@@ -87,7 +100,7 @@ export function detectChangedScope(changedPaths) {
87100
runNode = true;
88101
}
89102

90-
return { runNode, runMacos, runAndroid, runWindows, runSkillsPython };
103+
return { runNode, runMacos, runAndroid, runWindows, runSkillsPython, runChangedSmoke };
91104
}
92105

93106
/**
@@ -122,6 +135,7 @@ export function writeGitHubOutput(scope, outputPath = process.env.GITHUB_OUTPUT)
122135
appendFileSync(outputPath, `run_android=${scope.runAndroid}\n`, "utf8");
123136
appendFileSync(outputPath, `run_windows=${scope.runWindows}\n`, "utf8");
124137
appendFileSync(outputPath, `run_skills_python=${scope.runSkillsPython}\n`, "utf8");
138+
appendFileSync(outputPath, `run_changed_smoke=${scope.runChangedSmoke}\n`, "utf8");
125139
}
126140

127141
function isDirectRun() {
@@ -157,6 +171,7 @@ if (isDirectRun()) {
157171
runAndroid: true,
158172
runWindows: true,
159173
runSkillsPython: true,
174+
runChangedSmoke: true,
160175
});
161176
process.exit(0);
162177
}
@@ -168,6 +183,7 @@ if (isDirectRun()) {
168183
runAndroid: true,
169184
runWindows: true,
170185
runSkillsPython: true,
186+
runChangedSmoke: true,
171187
});
172188
}
173189
}

src/infra/scripts-modules.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,8 @@ declare module "../../scripts/ci-changed-scope.mjs" {
1818
runNode: boolean;
1919
runMacos: boolean;
2020
runAndroid: boolean;
21+
runWindows: boolean;
22+
runSkillsPython: boolean;
23+
runChangedSmoke: boolean;
2124
};
2225
}

src/scripts/ci-changed-scope.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const { detectChangedScope, listChangedPaths } =
1111
runAndroid: boolean;
1212
runWindows: boolean;
1313
runSkillsPython: boolean;
14+
runChangedSmoke: boolean;
1415
};
1516
listChangedPaths: (base: string, head?: string) => string[];
1617
};
@@ -34,6 +35,7 @@ describe("detectChangedScope", () => {
3435
runAndroid: true,
3536
runWindows: true,
3637
runSkillsPython: true,
38+
runChangedSmoke: true,
3739
});
3840
});
3941

@@ -44,6 +46,7 @@ describe("detectChangedScope", () => {
4446
runAndroid: false,
4547
runWindows: false,
4648
runSkillsPython: false,
49+
runChangedSmoke: false,
4750
});
4851
});
4952

@@ -54,6 +57,7 @@ describe("detectChangedScope", () => {
5457
runAndroid: false,
5558
runWindows: true,
5659
runSkillsPython: false,
60+
runChangedSmoke: false,
5761
});
5862
});
5963

@@ -64,13 +68,15 @@ describe("detectChangedScope", () => {
6468
runAndroid: false,
6569
runWindows: false,
6670
runSkillsPython: false,
71+
runChangedSmoke: false,
6772
});
6873
expect(detectChangedScope(["apps/shared/OpenClawKit/Sources/Foo.swift"])).toEqual({
6974
runNode: false,
7075
runMacos: true,
7176
runAndroid: true,
7277
runWindows: false,
7378
runSkillsPython: false,
79+
runChangedSmoke: false,
7480
});
7581
});
7682

@@ -82,6 +88,7 @@ describe("detectChangedScope", () => {
8288
runAndroid: false,
8389
runWindows: false,
8490
runSkillsPython: false,
91+
runChangedSmoke: false,
8592
},
8693
);
8794
});
@@ -93,6 +100,7 @@ describe("detectChangedScope", () => {
93100
runAndroid: false,
94101
runWindows: false,
95102
runSkillsPython: false,
103+
runChangedSmoke: false,
96104
});
97105

98106
expect(detectChangedScope(["assets/icon.png"])).toEqual({
@@ -101,6 +109,7 @@ describe("detectChangedScope", () => {
101109
runAndroid: false,
102110
runWindows: false,
103111
runSkillsPython: false,
112+
runChangedSmoke: false,
104113
});
105114
});
106115

@@ -111,6 +120,7 @@ describe("detectChangedScope", () => {
111120
runAndroid: false,
112121
runWindows: false,
113122
runSkillsPython: false,
123+
runChangedSmoke: false,
114124
});
115125
});
116126

@@ -121,6 +131,7 @@ describe("detectChangedScope", () => {
121131
runAndroid: false,
122132
runWindows: false,
123133
runSkillsPython: true,
134+
runChangedSmoke: false,
124135
});
125136
});
126137

@@ -131,6 +142,7 @@ describe("detectChangedScope", () => {
131142
runAndroid: false,
132143
runWindows: false,
133144
runSkillsPython: true,
145+
runChangedSmoke: false,
134146
});
135147
});
136148

@@ -141,6 +153,34 @@ describe("detectChangedScope", () => {
141153
runAndroid: true,
142154
runWindows: true,
143155
runSkillsPython: true,
156+
runChangedSmoke: false,
157+
});
158+
});
159+
160+
it("runs changed-smoke for install and packaging surfaces", () => {
161+
expect(detectChangedScope(["scripts/install.sh"])).toEqual({
162+
runNode: true,
163+
runMacos: false,
164+
runAndroid: false,
165+
runWindows: true,
166+
runSkillsPython: false,
167+
runChangedSmoke: true,
168+
});
169+
expect(detectChangedScope(["extensions/matrix/package.json"])).toEqual({
170+
runNode: true,
171+
runMacos: false,
172+
runAndroid: false,
173+
runWindows: true,
174+
runSkillsPython: false,
175+
runChangedSmoke: true,
176+
});
177+
expect(detectChangedScope([".github/workflows/install-smoke.yml"])).toEqual({
178+
runNode: true,
179+
runMacos: false,
180+
runAndroid: false,
181+
runWindows: false,
182+
runSkillsPython: false,
183+
runChangedSmoke: true,
144184
});
145185
});
146186

0 commit comments

Comments
 (0)