Skip to content

Commit 8263bf8

Browse files
Merge branch 'trunk' into fix/http-low-speed-timeout-for-ai-requests
2 parents 3e36973 + b8d8222 commit 8263bf8

2,054 files changed

Lines changed: 269442 additions & 43596 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.

.buildkite/commands/build-for-windows.ps1

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,13 @@ if ($Architecture -notin $VALID_ARCHITECTURES) {
2828
Exit 1
2929
}
3030

31-
# setup_windows_code_signing.ps1 comes from CI Toolkit Plugin
32-
& "setup_windows_code_signing.ps1"
33-
If ($LastExitCode -ne 0) { Exit $LastExitCode }
31+
$signWindows = "$($env:SIGN_WINDOWS_BUILD)".Trim().ToLower()
32+
If (@('1', 'true') -contains $signWindows) {
33+
Write-Host "--- :lock: Setting up Azure Trusted Signing"
34+
$setupScript = (Get-Command setup_azure_trusted_signing.ps1 -ErrorAction Stop).Source
35+
& $setupScript
36+
If ($LastExitCode -ne 0) { Exit $LastExitCode }
37+
}
3438

3539
Write-Host "--- :npm: Installing Node dependencies"
3640
bash .buildkite/commands/install-node-dependencies.sh
@@ -63,3 +67,7 @@ If ($LastExitCode -ne 0) { Exit $LastExitCode }
6367
Write-Host "--- :package: Building AppX package"
6468
node scripts/package-appx.mjs
6569
If ($LastExitCode -ne 0) { Exit $LastExitCode }
70+
71+
Write-Host "--- :package: Building standalone CLI bundle"
72+
npm run cli:bundle -- win32 $Architecture
73+
If ($LastExitCode -ne 0) { Exit $LastExitCode }

.buildkite/commands/install-node-dependencies.sh

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@ NODE_VERSION=$(node --version)
88
PACKAGE_HASH=$(hash_file package-lock.json)
99

1010
PATCHES_HASH=nopatch
11-
if [ -d apps/cli/patches ] || [ -d apps/studio/patches ]; then
12-
CLI_PATCHES_HASH=$( [ -d apps/cli/patches ] && hash_directory apps/cli/patches || echo none )
13-
STUDIO_PATCHES_HASH=$( [ -d apps/studio/patches ] && hash_directory apps/studio/patches || echo none )
14-
PATCHES_HASH="${CLI_PATCHES_HASH}-${STUDIO_PATCHES_HASH}"
11+
if [ -d apps/studio/patches ]; then
12+
PATCHES_HASH=$( hash_directory apps/studio/patches )
1513
fi
1614

1715
CACHEKEY="$BUILDKITE_PIPELINE_SLUG-npm-$PLATFORM-$ARCHITECTURE-node-$NODE_VERSION-$PACKAGE_HASH-$PATCHES_HASH"

.buildkite/commands/prepare-environment.sh

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,5 @@
66
echo "--- :rubygems: Setting up Gems"
77
install_gems
88

9-
echo "--- :closed_lock_with_key: Installing Secrets"
10-
bundle exec fastlane run configure_apply
11-
129
echo "--- :testflight: Fetching Signing Certificates"
13-
bundle exec fastlane set_up_signing
10+
bundle exec fastlane set_up_signing

.buildkite/commands/run-e2e-tests.sh

Lines changed: 154 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#!/usr/bin/env bash
22
set -euo pipefail
33

4+
trap 'echo "Termination signal received — failing the job."; exit 1' TERM INT
5+
46
PLATFORM=${1:?Expected platform to be provided as first parameter}
57
ARCH=${2:?Expected architecture to be provided as second parameter}
68

@@ -9,7 +11,39 @@ if .buildkite/commands/should-skip-job.sh --job-type validation; then
911
fi
1012

1113
echo '--- :package: Install deps'
12-
bash .buildkite/commands/install-node-dependencies.sh
14+
if [ "$PLATFORM" = "linux" ]; then
15+
# Linux runs inside a Debian Node container on the shared `default` queue.
16+
# The a8c-ci-toolkit cache helpers (hash_file, restore_cache) only exist on
17+
# the host, so install-node-dependencies.sh can't run here. Also install
18+
# Electron's runtime libraries plus xvfb (CI agents are headless) and the
19+
# browser dependencies Playwright would otherwise fetch via `npx playwright
20+
# install-deps` — same set, but apt is faster than letting Playwright shell
21+
# out to it again.
22+
apt-get -o Acquire::Retries=3 update
23+
apt-get install -y --no-install-recommends \
24+
xvfb \
25+
xauth \
26+
libcap2-bin \
27+
libnss3 \
28+
libatk1.0-0 \
29+
libatk-bridge2.0-0 \
30+
libcups2 \
31+
libdrm2 \
32+
libgtk-3-0 \
33+
libgbm1 \
34+
libasound2 \
35+
libxkbcommon0 \
36+
libxcomposite1 \
37+
libxdamage1 \
38+
libxfixes3 \
39+
libxrandr2 \
40+
libpango-1.0-0 \
41+
libcairo2 \
42+
libxss1
43+
npm ci --unsafe-perm --no-audit --no-progress --maxsockets 1
44+
else
45+
bash .buildkite/commands/install-node-dependencies.sh
46+
fi
1347

1448
export IS_DEV_BUILD=true
1549

@@ -21,6 +55,9 @@ case "$PLATFORM" in
2155
windows)
2256
FORGE_PLATFORM="win32"
2357
;;
58+
linux)
59+
FORGE_PLATFORM="linux"
60+
;;
2461
*)
2562
echo "Unknown platform: $PLATFORM"
2663
exit 1
@@ -33,10 +70,122 @@ esac
3370
echo "--- :package: Package app for testing ($PLATFORM-$ARCH)"
3471
npm -w studio-app run package -- --arch="$ARCH" --platform="$FORGE_PLATFORM"
3572

73+
if [ "$PLATFORM" = "linux" ]; then
74+
# The packaged app under apps/studio/out was created by electron-forge
75+
# running as root with restrictive default perms — the node user (which
76+
# runs Playwright below) gets EACCES on scandir without this. `X` (capital)
77+
# keeps directories traversable and existing executables executable,
78+
# without making every regular file executable.
79+
echo '--- :wrench: Open packaged app perms for non-root test user'
80+
chmod -R go+rX apps/studio/out
81+
82+
# Chromium's setuid sandbox helper (`chrome-sandbox`) requires real-root
83+
# ownership + setuid bit. Under Docker user-namespace remapping, the
84+
# container's "root" isn't real-root, so the kernel doesn't honor setuid
85+
# and Chromium aborts on the misconfigured helper. Removing the helper
86+
# makes Chromium skip the SUID path and fall through to the user-
87+
# namespace sandbox, which doesn't need setuid.
88+
rm -f "apps/studio/out/Studio-linux-${ARCH}/chrome-sandbox"
89+
90+
# Grant cap_net_bind_service to the bundled node so the proxy daemon can
91+
# listen on privileged ports 80/443 without running as root — mirrors the
92+
# DEB postinst hook (apps/studio/installers/linux/postinst.sh), which
93+
# doesn't run for `electron-forge package` output. Without this, custom-
94+
# domain HTTP/HTTPS tests fail to bind in the non-root test process.
95+
BUNDLED_NODE="apps/studio/out/Studio-linux-${ARCH}/resources/bin/node"
96+
if [ -x "$BUNDLED_NODE" ]; then
97+
echo '--- :shield: Grant cap_net_bind_service to bundled node'
98+
setcap 'cap_net_bind_service=+ep' "$BUNDLED_NODE" || \
99+
echo "warning: setcap failed on $BUNDLED_NODE; privileged-port tests may fail to bind." >&2
100+
fi
101+
fi
102+
103+
echo '--- :mag: Verify CLI build artifacts'
104+
CLI_DIST="apps/cli/dist/cli"
105+
missing=()
106+
for f in reprint-child.mjs main.mjs wp-files/reprint/reprint.phar; do
107+
[ -f "$CLI_DIST/$f" ] || missing+=("$f")
108+
done
109+
if [ ${#missing[@]} -gt 0 ]; then
110+
echo "Missing CLI build artifacts in $CLI_DIST: ${missing[*]}"
111+
exit 1
112+
fi
113+
echo "All required CLI build artifacts present."
114+
36115
echo '--- :playwright: Run End To End Tests'
37116

38-
echo 'Installing Playwright browsers...'
39-
npx playwright install
117+
# Electron needs a display server to launch. CI Linux agents are headless,
118+
# so wrap with xvfb-run to provide a virtual display.
119+
if [ "$PLATFORM" = "linux" ]; then
120+
# Run Playwright as the non-root `node` user (uid 1000, present in
121+
# node:bookworm). Electron's main delegate aborts with a FATAL on
122+
# `geteuid() == 0` in every helper subprocess; --no-sandbox from the
123+
# parent argv doesn't reliably propagate to all helper types, so the
124+
# only robust workaround is to not be root for the test invocation.
125+
#
126+
# We can't chown /workdir because Docker user-namespace remapping on
127+
# this agent denies cross-namespace chown even for container root.
128+
# Instead, redirect Playwright's output to /tmp (which node owns) and
129+
# copy results back to /workdir as root afterwards so the Buildkite
130+
# artifact uploader finds them under the configured artifact_paths.
131+
rm -rf /tmp/test-results
132+
mkdir -p /tmp/test-results
133+
chown node:node /tmp/test-results
134+
135+
# TODO(rsm-2593): --max-failures=1 is a temporary debug aid so the suite
136+
# bails on the first failing test instead of retrying through all of them
137+
# (~40 min on a broken Electron launch). Remove before merging.
138+
# Install only Chromium, not Firefox/Webkit. Our tests drive Electron via
139+
# Playwright's `_electron` API, but `test()` from `@playwright/test` still
140+
# auto-spins a Chromium-headless-shell for the default `page` fixture even
141+
# when the test body never touches it — so a Chromium install is required.
142+
# Skipping Firefox/Webkit avoids the noisy "missing dependencies"
143+
# validation against libs (gstreamer/flite/gtk-4/libavif/etc.) we don't
144+
# need. Run inside the `su node` block so the browser lands in the same
145+
# `~/.cache/ms-playwright` that the test process reads from.
146+
test_exit=0
147+
su -s /bin/bash node -c '
148+
set -euo pipefail
149+
cd /workdir
150+
echo "Installing Playwright Chromium..."
151+
npx playwright install chromium
152+
echo "Running Playwright tests..."
153+
# Explicit screen size: xvfb-run defaults to 1280x1024, which can leave
154+
# right-edge content (e.g. the preferences Save button) below the fold
155+
# for the split-pane settings layout. 1920x1080 matches a typical
156+
# desktop and avoids relying on scroll-into-view.
157+
inner_exit=0
158+
xvfb-run -a -s "-screen 0 1920x1080x24" \
159+
npx playwright test --max-failures=1 --output=/tmp/test-results || inner_exit=$?
160+
# On failure, collect daemon logs into /tmp/test-results (copied to the
161+
# artifact dir below). $HOME here is the node user that ran the tests.
162+
if [ "$inner_exit" -ne 0 ] && [ -d "$HOME/.studio/daemon/logs" ]; then
163+
cp -r "$HOME/.studio/daemon/logs" /tmp/test-results/daemon-logs || true
164+
fi
165+
exit "$inner_exit"
166+
' || test_exit=$?
167+
168+
if [ -d /tmp/test-results ]; then
169+
echo '--- :file_folder: Copy test results for artifact upload'
170+
mkdir -p test-results
171+
cp -r /tmp/test-results/. test-results/ || true
172+
fi
173+
174+
exit "$test_exit"
175+
else
176+
echo 'Installing Playwright browsers...'
177+
npx playwright install
40178

41-
echo 'Running Playwright tests...'
42-
npx playwright test
179+
echo 'Running Playwright tests...'
180+
# Capture the exit code so a failure doesn't trip `set -e` before we collect
181+
# the daemon logs (~/.studio/daemon/logs) for artifact upload.
182+
test_exit=0
183+
npx playwright test || test_exit=$?
184+
185+
if [ "$test_exit" -ne 0 ] && [ -d "$HOME/.studio/daemon/logs" ]; then
186+
mkdir -p test-results/daemon-logs
187+
cp -r "$HOME/.studio/daemon/logs/." test-results/daemon-logs/ || true
188+
fi
189+
190+
exit "$test_exit"
191+
fi
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
if .buildkite/commands/should-skip-job.sh --job-type fastlane; then
6+
exit 0
7+
fi
8+
9+
echo '--- :fastlane: Run fastlane Helper Tests'
10+
for test_file in fastlane/test/*_test.rb; do
11+
ruby "$test_file"
12+
done

.buildkite/commands/run-unit-tests.sh

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,14 @@ if .buildkite/commands/should-skip-job.sh --job-type validation; then
88
fi
99

1010
echo '--- :package: Install deps'
11-
bash .buildkite/commands/install-node-dependencies.sh
11+
if [ "$MATRIX" = "linux" ]; then
12+
# Linux runs inside a Docker container; the a8c-ci-toolkit cache helpers
13+
# (hash_file, restore_cache) only exist on the host, so install-node-
14+
# dependencies.sh can't run here. Run npm ci directly instead.
15+
npm ci --unsafe-perm --no-audit --no-progress --maxsockets 1
16+
else
17+
bash .buildkite/commands/install-node-dependencies.sh
18+
fi
1219

1320
echo '--- :npm: Run Unit Tests'
1421
npm run test

.buildkite/commands/should-skip-job.sh

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ set -eu
1414
# Since metrics measure app performance, test file changes don't affect them.
1515
# - build: Skip if changes are limited to documentation and config files.
1616
# Does NOT skip on localization changes since builds should include translation updates.
17+
# - fastlane: Inverse of the others — only runs when fastlane/ or Ruby setup files change.
18+
# Used for the standalone tests in fastlane/test/. App-only PRs skip it.
1719
#
1820
# Exit codes:
1921
# 0 - Job should be skipped
@@ -62,7 +64,7 @@ COMMON_NON_CODE_PATTERNS=(
6264

6365
# Localization files - changes here don't affect runtime behavior or performance
6466
LOCALIZATION_PATTERNS=(
65-
"tools/common/translations/**"
67+
"packages/common/translations/**"
6668
)
6769

6870
# Test files - changes here don't affect app performance (for metrics)
@@ -72,10 +74,24 @@ TEST_PATTERNS=(
7274
"apps/studio/src/**/*.test.ts"
7375
"apps/studio/src/**/*.test.tsx"
7476
"apps/cli/**/*.test.ts"
75-
"tools/common/**/*.test.ts"
77+
"packages/common/**/*.test.ts"
7678
"metrics/**"
7779
)
7880

81+
# Fastlane / Ruby setup files - changes here affect the standalone fastlane
82+
# helper tests. Anything that the test runner reads (Fastfile, lib/, test/),
83+
# that defines the Ruby environment, or that implements this CI job's runner /
84+
# skip logic belongs here.
85+
FASTLANE_PATTERNS=(
86+
"fastlane/**"
87+
"Gemfile"
88+
"Gemfile.lock"
89+
".ruby-version"
90+
".bundle/**"
91+
".buildkite/commands/run-fastlane-tests.sh"
92+
".buildkite/commands/should-skip-job.sh"
93+
)
94+
7995
show_skip_message() {
8096
local job_type=$1
8197
local job_label="${BUILDKITE_LABEL:-$job_type}"
@@ -107,7 +123,7 @@ done
107123

108124
if [[ -z "$job_type" ]]; then
109125
echo "Error: --job-type is required"
110-
echo "Usage: should-skip-job.sh --job-type <validation|metrics|build>"
126+
echo "Usage: should-skip-job.sh --job-type <validation|metrics|build|fastlane>"
111127
exit 1
112128
fi
113129

@@ -147,9 +163,18 @@ case "$job_type" in
147163
fi
148164
;;
149165

166+
"fastlane")
167+
# Run only if at least one changed file is fastlane/ or Ruby-setup-related.
168+
# Other job types treat fastlane changes as non-code; this one is the inverse.
169+
if ! pr_changed_files --any-match "${FASTLANE_PATTERNS[@]}"; then
170+
show_skip_message "$job_type"
171+
exit 0
172+
fi
173+
;;
174+
150175
*)
151176
echo "Unknown job type: $job_type"
152-
echo "Valid types: validation, metrics, build"
177+
echo "Valid types: validation, metrics, build, fastlane"
153178
exit 1
154179
;;
155180
esac

0 commit comments

Comments
 (0)