Skip to content

Commit 6ea0168

Browse files
committed
Merge remote-tracking branch 'upstream/main' into codex/agnes-ai-byok-provider-pr
# Conflicts: # apps/web/src/state/config.ts
2 parents bb64b7d + 0dde0e5 commit 6ea0168

1,356 files changed

Lines changed: 285316 additions & 32732 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/actions/configure-ci-parallelism/action.yml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: Configure CI parallelism
2-
description: Export CI worker counts derived from nproc/2
2+
description: Export build worker counts derived from nproc/2 with a memory-safe Playwright cap
33

44
runs:
55
using: composite
@@ -14,14 +14,18 @@ runs:
1414
if [ "$workers" -lt 1 ]; then
1515
workers=1
1616
fi
17+
playwright_workers="$workers"
18+
if [ "$playwright_workers" -gt 2 ]; then
19+
playwright_workers=2
20+
fi
1721
1822
{
1923
echo "OPEN_DESIGN_POSTINSTALL_CONCURRENCY=$workers"
2024
echo "OPEN_DESIGN_WORKSPACE_CONCURRENCY=$workers"
2125
echo "OD_CI_DAEMON_MAX_WORKERS=$workers"
2226
echo "OD_E2E_VITEST_MAX_WORKERS=$workers"
23-
echo "OD_PLAYWRIGHT_WORKERS=$workers"
27+
echo "OD_PLAYWRIGHT_WORKERS=$playwright_workers"
2428
} >> "$GITHUB_ENV"
2529
2630
echo "workers=$workers" >> "$GITHUB_OUTPUT"
27-
echo "nproc=$cpu_count workers=$workers"
31+
echo "nproc=$cpu_count workers=$workers playwright_workers=$playwright_workers"

.github/actions/setup-playwright/action.yml

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: Setup Playwright
2-
description: Restore Playwright browser cache and install browsers
2+
description: Use a preseeded Nexu browser when available, otherwise restore the browser cache and install browsers
33

44
inputs:
55
package-json-path:
@@ -16,8 +16,40 @@ inputs:
1616
runs:
1717
using: composite
1818
steps:
19+
- name: Detect preinstalled Playwright
20+
id: preinstalled-playwright
21+
shell: bash
22+
env:
23+
RUNNER_LABELS_JSON: ${{ inputs.runner-labels }}
24+
run: |
25+
preinstalled_enabled=false
26+
27+
# The ARC tools image carries both the OS dependencies and Chromium.
28+
# Keep this opt-in to the named Nexu profiles so a hosted runner with
29+
# a restored browser cache still receives its OS dependencies.
30+
case "$RUNNER_LABELS_JSON" in
31+
*'"nexu-runners-'*)
32+
if [ -n "${PLAYWRIGHT_BROWSERS_PATH:-}" ] && [ -d "$PLAYWRIGHT_BROWSERS_PATH" ]; then
33+
chromium_bin="$(find "$PLAYWRIGHT_BROWSERS_PATH" -type f \
34+
\( -name chrome -o -name chromium -o -name chrome-headless-shell \) \
35+
-perm -111 -print -quit 2>/dev/null || true)"
36+
if [ -n "$chromium_bin" ]; then
37+
preinstalled_enabled=true
38+
fi
39+
fi
40+
;;
41+
esac
42+
43+
echo "enabled=$preinstalled_enabled" >> "$GITHUB_OUTPUT"
44+
if [ "$preinstalled_enabled" = "true" ]; then
45+
echo "Using the Playwright browser preseeded in the Nexu runner image."
46+
else
47+
echo "No preseeded Playwright browser detected; using the workflow install path."
48+
fi
49+
1950
- name: Detect persistent Playwright cache
2051
id: persistent-playwright-cache
52+
if: ${{ steps.preinstalled-playwright.outputs.enabled != 'true' }}
2153
shell: bash
2254
env:
2355
RUNNER_LABELS_JSON: ${{ inputs.runner-labels }}
@@ -41,6 +73,7 @@ runs:
4173
4274
- name: Resolve Playwright version
4375
id: playwright-version
76+
if: ${{ steps.preinstalled-playwright.outputs.enabled != 'true' }}
4477
shell: bash
4578
run: |
4679
version=$(node -p "const pkg = require('./${{ inputs.package-json-path }}'); const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) }; (deps['@playwright/test'] || deps.playwright || '').replace(/[^0-9.]/g,'')")
@@ -51,12 +84,22 @@ runs:
5184
echo "version=$version" >> "$GITHUB_OUTPUT"
5285
5386
- name: Cache Playwright browser binaries
54-
if: ${{ steps.persistent-playwright-cache.outputs.enabled != 'true' }}
87+
if: ${{ steps.preinstalled-playwright.outputs.enabled != 'true' && steps.persistent-playwright-cache.outputs.enabled != 'true' }}
5588
uses: actions/cache@v5.0.5
5689
with:
5790
path: ~/.cache/ms-playwright
5891
key: playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }}
5992

93+
- name: Ensure preinstalled Playwright browser revision
94+
if: ${{ steps.preinstalled-playwright.outputs.enabled == 'true' }}
95+
shell: bash
96+
env:
97+
PACKAGE_JSON_PATH: ${{ inputs.package-json-path }}
98+
run: |
99+
package_dir="${PACKAGE_JSON_PATH%/*}"
100+
pnpm -C "$package_dir" exec playwright install chromium
101+
60102
- name: Install Playwright browsers
103+
if: ${{ steps.preinstalled-playwright.outputs.enabled != 'true' }}
61104
shell: bash
62105
run: ${{ inputs.install-command }}

.github/actions/setup-workspace/action.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,17 @@ runs:
4747
echo "enabled=true" >> "$GITHUB_OUTPUT"
4848
echo "path=$store_dir" >> "$GITHUB_OUTPUT"
4949
else
50+
# Force a stable home store path so actions/cache version hashes match
51+
# across fleets (hosted vs Nexu ARC). ARC may copy instead of hardlink;
52+
# that is acceptable for cache hit stability.
53+
store_dir="$HOME/.pnpm-store"
54+
mkdir -p "$store_dir"
55+
{
56+
echo "NPM_CONFIG_STORE_DIR=$store_dir"
57+
echo "npm_config_store_dir=$store_dir"
58+
} >> "$GITHUB_ENV"
5059
echo "enabled=false" >> "$GITHUB_OUTPUT"
60+
echo "path=$store_dir" >> "$GITHUB_OUTPUT"
5161
fi
5262
5363
- name: Setup pnpm
@@ -73,6 +83,8 @@ runs:
7383
with:
7484
path: ${{ steps.pnpm-store.outputs.path }}
7585
key: pnpm-store-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
86+
restore-keys: |
87+
pnpm-store-${{ runner.os }}-
7688
7789
- name: Install dependencies
7890
shell: bash

.github/scripts/runners.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,41 @@
77

88
GITHUB_HOSTED = ["ubuntu-24.04"]
99
WINDOWS_HOSTED = ["windows-latest"]
10-
CONTABO_CONTROL = ["self-hosted", "Linux", "X64", "od-persistent-ci", "od-ci-hot-poc"]
11-
BLACKSMITH_4V = ["blacksmith-4vcpu-ubuntu-2404"]
10+
NEXU_SMALL = ["nexu-runners-small"]
11+
NEXU_MEDIUM = ["nexu-runners-medium"]
12+
NEXU_LARGE = ["nexu-runners-large"]
13+
NEXU_XLARGE = ["nexu-runners-xlarge"]
1214

1315

1416
def compact_json(value):
1517
return json.dumps(value, separators=(",", ":"))
1618

1719

1820
def normalize_mode(raw_mode):
19-
mode = (raw_mode or "default").strip().lower()
21+
mode = raw_mode or "default"
2022
if mode in {"default", "performance", "economic"}:
2123
return mode
2224
return "default"
2325

2426

2527
def resolve_contract(mode):
26-
general_medium = BLACKSMITH_4V if mode == "performance" else GITHUB_HOSTED
27-
hot_path = GITHUB_HOSTED if mode == "economic" else BLACKSMITH_4V
28-
control = CONTABO_CONTROL if mode == "default" else GITHUB_HOSTED
28+
control = GITHUB_HOSTED if mode == "economic" else NEXU_SMALL
29+
workload = GITHUB_HOSTED if mode == "economic" else NEXU_MEDIUM
30+
browser_workload = GITHUB_HOSTED if mode == "economic" else NEXU_LARGE
31+
# UI P0 is the memory-heavy Playwright domain suite; prefer the dedicated
32+
# xlarge class once available so large remains headroom for lighter UI jobs.
33+
ui_p0_workload = GITHUB_HOSTED if mode == "economic" else NEXU_XLARGE
2934

3035
return {
3136
"runs_on": {
3237
"control": control,
33-
"general_medium": general_medium,
34-
"workspace_unit": GITHUB_HOSTED,
38+
"general_medium": workload,
39+
"workspace_unit": workload,
3540
"windows_tools": WINDOWS_HOSTED,
36-
"js_hot": hot_path,
37-
"ui_hot": hot_path,
38-
"visual_hot": hot_path,
41+
"js_hot": workload,
42+
"ui_hot": browser_workload,
43+
"ui_p0": ui_p0_workload,
44+
"visual_hot": browser_workload,
3945
},
4046
"decision": {
4147
"schema_version": 1,

.github/workflows/backport-label-guard.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ name: backport-label-guard
33
# when someone applies a backport label, verify they have write+ permission (this includes
44
# outside collaborators granted write). If not, remove the label and comment. Removing a label
55
# fires the "unlabeled" event, not "labeled", so there is no loop.
6+
# GitHub App bots never appear in the collaborators API (permission reads as "none"), so
7+
# trusted automation apps are allowlisted by login instead.
68

79
on:
810
pull_request_target:
@@ -31,6 +33,10 @@ jobs:
3133
REPO: ${{ github.repository }}
3234
run: |
3335
set -euo pipefail
36+
if [ "$ACTOR" = "open-design-crew[bot]" ]; then
37+
echo "Authorized: $ACTOR (allowlisted app)"
38+
exit 0
39+
fi
3440
perm=$(gh api "repos/$REPO/collaborators/$ACTOR/permission" --jq '.permission' 2>/dev/null || echo none)
3541
case "$perm" in
3642
admin|maintain|write)

.github/workflows/cache-maintenance.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,23 @@ jobs:
2929
with:
3030
save-pnpm-cache: 'true'
3131

32+
33+
# GHA actions/cache is repo-scoped and shared across hosted + every Nexu
34+
# size (small/medium/large). One Linux seed under the pinned home store path
35+
# is enough for the whole fleet; no per-size matrix required.
36+
seed-pnpm-linux:
37+
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main')
38+
runs-on: ubuntu-24.04
39+
timeout-minutes: 15
40+
steps:
41+
- name: Checkout main
42+
uses: actions/checkout@v6.0.2
43+
44+
- name: Seed Linux pnpm cache
45+
uses: ./.github/actions/setup-workspace
46+
with:
47+
save-pnpm-cache: 'true'
48+
3249
clean-closed-pr-buildkit:
3350
if: github.event_name == 'pull_request_target' && github.repository == 'nexu-io/open-design'
3451
runs-on: ubuntu-24.04

.github/workflows/ci.yml

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,14 @@ concurrency:
3131
jobs:
3232
runners:
3333
name: Resolve runner profiles
34-
runs-on: ubuntu-24.04
34+
# Resolve on the Nexu ARC fleet for trusted branches, but preserve the
35+
# hosted bootstrap path for external forks and explicit economic mode.
36+
runs-on: >-
37+
${{ ((github.event_name == 'pull_request'
38+
&& github.event.pull_request.head.repo.full_name != github.repository)
39+
|| vars.OD_CI_RUNNER_MODE == 'economic')
40+
&& 'ubuntu-24.04'
41+
|| 'nexu-runners-small' }}
3542
outputs:
3643
runs_on: ${{ steps.runners.outputs.runs_on }}
3744
decision: ${{ steps.runners.outputs.decision }}
@@ -43,7 +50,13 @@ jobs:
4350
- name: Resolve runner profiles
4451
id: runners
4552
env:
46-
OD_CI_RUNNER_MODE: ${{ vars.OD_CI_RUNNER_MODE }}
53+
# Fork PRs cannot rely on repository variables, so keep their required
54+
# validation on GitHub-hosted runners even when private pools are down.
55+
OD_CI_RUNNER_MODE: >-
56+
${{ github.event_name == 'pull_request'
57+
&& github.event.pull_request.head.repo.full_name != github.repository
58+
&& 'economic'
59+
|| vars.OD_CI_RUNNER_MODE }}
4760
run: python3 .github/scripts/runners.py
4861

4962
scopes:
@@ -353,11 +366,15 @@ jobs:
353366
run: pnpm --filter @open-design/tools-pack exec vitest run tests/launcher-payload.test.ts
354367

355368
web_workspace_tests:
356-
name: Web workspace tests
369+
name: Web workspace tests (${{ matrix.shard }}/2)
357370
needs: [scopes, runners]
358371
if: ${{ needs.scopes.outputs.run_web_workspace_tests == 'true' }}
359372
runs-on: ${{ fromJSON(needs.runners.outputs.runs_on).js_hot }}
360373
timeout-minutes: 20
374+
strategy:
375+
fail-fast: false
376+
matrix:
377+
shard: [1, 2]
361378

362379
steps:
363380
- name: Checkout
@@ -375,7 +392,7 @@ jobs:
375392
run: pnpm --filter @open-design/web build:sidecar
376393

377394
- name: Web workspace tests
378-
run: pnpm --filter @open-design/web test
395+
run: pnpm --filter @open-design/web exec vitest run -c vitest.config.ts --maxWorkers=2 --shard=${{ matrix.shard }}/2
379396

380397
e2e_vitest:
381398
name: E2E Vitest
@@ -464,7 +481,7 @@ jobs:
464481
name: UI P0 (${{ matrix.name }})
465482
needs: [scopes, runners]
466483
if: ${{ needs.scopes.outputs.run_ui_p0 == 'true' }}
467-
runs-on: ${{ fromJSON(needs.runners.outputs.runs_on).ui_hot }}
484+
runs-on: ${{ fromJSON(needs.runners.outputs.runs_on).ui_p0 }}
468485
timeout-minutes: 45
469486
strategy:
470487
fail-fast: false
@@ -481,14 +498,14 @@ jobs:
481498
- name: Setup workspace
482499
uses: ./.github/actions/setup-workspace
483500
with:
484-
runner-labels: ${{ toJSON(fromJSON(needs.runners.outputs.runs_on).ui_hot) }}
501+
runner-labels: ${{ toJSON(fromJSON(needs.runners.outputs.runs_on).ui_p0) }}
485502

486503
- name: Setup Playwright
487504
uses: ./.github/actions/setup-playwright
488505
with:
489506
package-json-path: e2e/package.json
490507
install-command: pnpm -C e2e exec playwright install --with-deps chromium
491-
runner-labels: ${{ toJSON(fromJSON(needs.runners.outputs.runs_on).ui_hot) }}
508+
runner-labels: ${{ toJSON(fromJSON(needs.runners.outputs.runs_on).ui_p0) }}
492509

493510
- name: Prebuild workspace type declarations
494511
run: |
@@ -601,6 +618,7 @@ jobs:
601618
name: visual-pr-capture-${{ github.event.pull_request.number }}-${{ github.run_id }}-${{ matrix.name }}
602619
path: |
603620
e2e/ui/reports/visual-screenshots
621+
e2e/ui/reports/visual-test-results
604622
e2e/ui/reports/visual-results.json
605623
e2e/ui/reports/visual-report/manifest.json
606624
if-no-files-found: ignore
@@ -613,6 +631,7 @@ jobs:
613631
name: visual-ci-${{ github.run_id }}-${{ matrix.name }}
614632
path: |
615633
e2e/ui/reports/visual-screenshots
634+
e2e/ui/reports/visual-test-results
616635
e2e/ui/reports/visual-results.json
617636
if-no-files-found: ignore
618637
retention-days: 7
@@ -740,6 +759,8 @@ jobs:
740759
handoff_dir="$(python3 .github/scripts/handoff.py dir comment "$handoff_id" --root "$handoff_root")"
741760
mkdir -p "$handoff_dir"
742761
marker="<!-- merge-queue-needs-validation -->"
762+
# Markdown code spans are intentionally literal in these single-quoted strings.
763+
# shellcheck disable=SC2016
743764
{
744765
printf '%s\n' "$marker"
745766
# Markdown code spans are intentional literal text.

.github/workflows/notify-release-feishu.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ on:
3636
required: false
3737
type: string
3838
default: ""
39+
amr_profile:
40+
description: "Optional AMR profile to bake (test / feature-test enable the Workspace Team transport). Empty uses the per-branch default: test on release/v0.18.0, otherwise prod."
41+
required: false
42+
type: string
43+
default: ""
44+
win_x64_smoke_mode:
45+
description: "Windows x64 packaged smoke coverage (skip/core/full). Empty uses the per-branch default: skip on release/v0.18.0 to bypass the known packaged-win smoke flake that gates publish, otherwise release-prerelease's own default."
46+
required: false
47+
type: string
48+
default: ""
3949

4050
permissions:
4151
contents: write
@@ -65,6 +75,23 @@ jobs:
6575
# version). Only set when building from a non-release ref like main, where
6676
# release-prerelease cannot derive the base version from the branch name.
6777
release_version: ${{ inputs.release_version }}
78+
# Workspace Team profile baked into the packaged build (see
79+
# apps/packaged/src/workspace-team.ts + release-prerelease.yml). Release
80+
# builds ship `prod`: production's Vela backend now serves the feature, so
81+
# a release prerelease points users at the production console rather than
82+
# an internal test environment. A manual dispatch can still override to
83+
# test / feature-test to cut a build against those backends.
84+
#
85+
# (This replaces a temporary `test` default on release/v0.18.0 that
86+
# existed only while prod's resource-hub storage was unconfigured.)
87+
amr_profile: ${{ inputs.amr_profile || 'prod' }}
88+
# Windows packaged smoke is a hard publish gate (publish needs build_win
89+
# success) but currently flakes on release/v0.18.0 ("did not reach main app
90+
# shell"), skip-blocking EVERY platform's publish + the Feishu card. TEMPORARY:
91+
# skip it on release/v0.18.0 so the workspace-team prerelease can actually
92+
# ship its mac/win/linux packages + post its card. Manual dispatch overrides.
93+
# Remove this branch default once the win smoke flake root cause is fixed.
94+
win_x64_smoke_mode: ${{ inputs.win_x64_smoke_mode || (github.ref_name == 'release/v0.18.0' && 'skip') || '' }}
6895

6996
notify:
7097
name: Notify Feishu (release)

0 commit comments

Comments
 (0)