ci: route UI P0 jobs onto nexu-runners-xlarge (#6466)

UI P0 (especially project-collab) regularly drives the large runner
container working set to the 16Gi limit. Add a dedicated ui_p0 profile
on nexu-runners-xlarge and keep lighter browser jobs on large.
This commit is contained in:
Marc Chan
2026-08-05 11:41:14 +00:00
committed by GitHub
parent 20c2d9da18
commit 8e3853f0bc
4 changed files with 18 additions and 8 deletions
+5
View File
@@ -10,6 +10,7 @@ WINDOWS_HOSTED = ["windows-latest"]
NEXU_SMALL = ["nexu-runners-small"]
NEXU_MEDIUM = ["nexu-runners-medium"]
NEXU_LARGE = ["nexu-runners-large"]
NEXU_XLARGE = ["nexu-runners-xlarge"]
def compact_json(value):
@@ -27,6 +28,9 @@ def resolve_contract(mode):
control = GITHUB_HOSTED if mode == "economic" else NEXU_SMALL
workload = GITHUB_HOSTED if mode == "economic" else NEXU_MEDIUM
browser_workload = GITHUB_HOSTED if mode == "economic" else NEXU_LARGE
# UI P0 is the memory-heavy Playwright domain suite; prefer the dedicated
# xlarge class once available so large remains headroom for lighter UI jobs.
ui_p0_workload = GITHUB_HOSTED if mode == "economic" else NEXU_XLARGE
return {
"runs_on": {
@@ -36,6 +40,7 @@ def resolve_contract(mode):
"windows_tools": WINDOWS_HOSTED,
"js_hot": workload,
"ui_hot": browser_workload,
"ui_p0": ui_p0_workload,
"visual_hot": browser_workload,
},
"decision": {
+3 -3
View File
@@ -477,7 +477,7 @@ jobs:
name: UI P0 (${{ matrix.name }})
needs: [scopes, runners]
if: ${{ needs.scopes.outputs.run_ui_p0 == 'true' }}
runs-on: ${{ fromJSON(needs.runners.outputs.runs_on).ui_hot }}
runs-on: ${{ fromJSON(needs.runners.outputs.runs_on).ui_p0 }}
timeout-minutes: 45
strategy:
fail-fast: false
@@ -494,14 +494,14 @@ jobs:
- name: Setup workspace
uses: ./.github/actions/setup-workspace
with:
runner-labels: ${{ toJSON(fromJSON(needs.runners.outputs.runs_on).ui_hot) }}
runner-labels: ${{ toJSON(fromJSON(needs.runners.outputs.runs_on).ui_p0) }}
- name: Setup Playwright
uses: ./.github/actions/setup-playwright
with:
package-json-path: e2e/package.json
install-command: pnpm -C e2e exec playwright install --with-deps chromium
runner-labels: ${{ toJSON(fromJSON(needs.runners.outputs.runs_on).ui_hot) }}
runner-labels: ${{ toJSON(fromJSON(needs.runners.outputs.runs_on).ui_p0) }}
- name: Prebuild workspace type declarations
run: |
+3 -3
View File
@@ -42,7 +42,7 @@ jobs:
name: UI P0 (${{ matrix.name }})
needs: [p0_runners]
if: ${{ github.repository == 'nexu-io/open-design' && github.event_name == 'workflow_dispatch' && inputs.suite != 'full' }}
runs-on: ${{ fromJSON(needs.p0_runners.outputs.runs_on).ui_hot }}
runs-on: ${{ fromJSON(needs.p0_runners.outputs.runs_on).ui_p0 }}
timeout-minutes: 45
strategy:
fail-fast: false
@@ -67,14 +67,14 @@ jobs:
- name: Setup workspace
uses: ./.github/actions/setup-workspace
with:
runner-labels: ${{ toJSON(fromJSON(needs.p0_runners.outputs.runs_on).ui_hot) }}
runner-labels: ${{ toJSON(fromJSON(needs.p0_runners.outputs.runs_on).ui_p0) }}
- name: Setup Playwright
uses: ./.github/actions/setup-playwright
with:
package-json-path: e2e/package.json
install-command: pnpm -C e2e exec playwright install --with-deps chromium
runner-labels: ${{ toJSON(fromJSON(needs.p0_runners.outputs.runs_on).ui_hot) }}
runner-labels: ${{ toJSON(fromJSON(needs.p0_runners.outputs.runs_on).ui_p0) }}
- name: Prebuild workspace type declarations
run: |
+7 -2
View File
@@ -1153,8 +1153,8 @@ process.stdin.on("end", () => {
expect(e2eVitest).not.toContain('"od-persistent-ci"');
expect(preflight).toContain("fromJSON(needs.runners.outputs.runs_on).general_medium");
expect(preflight).toContain("toJSON(fromJSON(needs.runners.outputs.runs_on).general_medium)");
expect(uiP0).toContain("fromJSON(needs.runners.outputs.runs_on).ui_hot");
expect(uiP0).toContain("toJSON(fromJSON(needs.runners.outputs.runs_on).ui_hot)");
expect(uiP0).toContain("fromJSON(needs.runners.outputs.runs_on).ui_p0");
expect(uiP0).toContain("toJSON(fromJSON(needs.runners.outputs.runs_on).ui_p0)");
expect(uiP0).toContain("include: ${{ fromJSON(needs.scopes.outputs.ui_p0_matrix) }}");
expect(uiP0CiMatrix.map((entry) => entry.name)).toEqual([
"entry-settings",
@@ -1247,6 +1247,7 @@ process.stdin.on("end", () => {
expect(benchmarkWorkflow).toContain("Preserve project-runtime domain artifact");
expect(benchmarkWorkflow).toContain("--grep-invert '@merge-extra'");
expect(benchmarkWorkflow).toContain("name: project-workspace");
expect(benchmarkWorkflow).toContain("fromJSON(needs.p0_runners.outputs.runs_on).ui_p0");
expect(fullUi).toContain("fromJSON(needs.p0_runners.outputs.runs_on).ui_hot");
expect(fullUi).toContain("shard: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]");
expect(fullUi).toContain('OD_PLAYWRIGHT_FULLY_PARALLEL: "1"');
@@ -1268,6 +1269,7 @@ process.stdin.on("end", () => {
"general_medium",
"js_hot",
"ui_hot",
"ui_p0",
"visual_hot",
"windows_tools",
"workspace_unit",
@@ -1278,6 +1280,7 @@ process.stdin.on("end", () => {
expect(defaultRunsOn.windows_tools).toEqual(["windows-latest"]);
expect(defaultRunsOn.js_hot).toEqual(["nexu-runners-medium"]);
expect(defaultRunsOn.ui_hot).toEqual(["nexu-runners-large"]);
expect(defaultRunsOn.ui_p0).toEqual(["nexu-runners-xlarge"]);
expect(defaultRunsOn.visual_hot).toEqual(["nexu-runners-large"]);
expect(defaultProfiles).not.toHaveProperty("contabo_control");
expect(defaultProfiles).not.toHaveProperty("hosted_or_blacksmith");
@@ -1292,6 +1295,7 @@ process.stdin.on("end", () => {
expect(performanceRunsOn.windows_tools).toEqual(["windows-latest"]);
expect(performanceRunsOn.js_hot).toEqual(["nexu-runners-medium"]);
expect(performanceRunsOn.ui_hot).toEqual(["nexu-runners-large"]);
expect(performanceRunsOn.ui_p0).toEqual(["nexu-runners-xlarge"]);
expect(performanceRunsOn.visual_hot).toEqual(["nexu-runners-large"]);
const economicProfiles = await runRunners("economic");
@@ -1303,6 +1307,7 @@ process.stdin.on("end", () => {
expect(economicRunsOn.windows_tools).toEqual(["windows-latest"]);
expect(economicRunsOn.js_hot).toEqual(["ubuntu-24.04"]);
expect(economicRunsOn.ui_hot).toEqual(["ubuntu-24.04"]);
expect(economicRunsOn.ui_p0).toEqual(["ubuntu-24.04"]);
expect(economicRunsOn.visual_hot).toEqual(["ubuntu-24.04"]);
for (const invalidMode of ["Economic", " economic "]) {