mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 19:17:10 +00:00
ci: fix the node 20 warning and pin the protoc plugins (#84)
* ci: replace the archived buf-setup-action with buf-action
buf-setup-action is archived and runs on node20, which the runners now
warn about. buf-action is its supported replacement and runs on node24.
setup_only keeps it an install, since buf lint is its own step.
* ci: bump bun to 1.3.14
* ci: bump setup-chrome to v2.2.0
* ci: move to node 24 and drop the npm oidc workaround
node 22 is in maintenance and ships npm 10, which is why the publish job
had to install npm@latest over it. node 24 is the active lts and bundles
npm 11.17.0, above the 11.5.1 oidc floor, so the extra step goes.
* ci: pin the protoc plugins instead of installing @latest
these generate the committed stubs, so @latest makes codegen depend on
whatever released most recently. pinned to the versions proto/ records:
protoc-gen-go v1.36.11, protoc-gen-go-grpc v1.6.0.
* ci: run the ios leg on macos-26, pinned to a device and a runtime
macos-26 carries no iPhone 16 Pro at all, and on macos-15 that name spanned
iOS 18.5 through 26.2, so the leg could boot a two-major-old runtime. the
pair is now iPhone 17 Pro on iOS 26.2, resolved to a udid before boot, and
an image that drops it fails naming what it does carry.
iPhone 17 Pro is what examples/folio/justfile already defaulted to.
* ci: keep IOS_DEVICE a device name, not the resolved udid
the boot step exported the udid as IOS_DEVICE, and just ios spends that as
xcodebuild's -destination name=, which matches the display name and
rejected it: 'unable to find a device matching { name:6F69910C-... }'.
nothing downstream needed it. install, launch and terminate all address
booted, and sanderling resolves --ios-device against booted simulators
first, so the simulator this step boots is the one they all get.
This commit is contained in:
5 files changed
+88
-29
No files matched your search
@@ -8,7 +8,7 @@ runs:
|
|||||||
# the action cannot move the browser these jobs drive. The alternative it
|
# the action cannot move the browser these jobs drive. The alternative it
|
||||||
# offers is Chrome for Testing latest, which tracks ahead of the channel
|
# offers is Chrome for Testing latest, which tracks ahead of the channel
|
||||||
# users run.
|
# users run.
|
||||||
- uses: browser-actions/setup-chrome@2e1d749697dd1612b833dba4a722266286fbefcd # v2.1.2
|
- uses: browser-actions/setup-chrome@48ad923757ca74d66703209fe939badbdf80f2f4 # v2.2.0
|
||||||
with:
|
with:
|
||||||
chrome-version: stable
|
chrome-version: stable
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ expect_argv "--seed" argv-ios
|
|||||||
expect_argv "7" argv-ios
|
expect_argv "7" argv-ios
|
||||||
expect_argv "240" argv-ios
|
expect_argv "240" argv-ios
|
||||||
expect_argv "20m" argv-ios
|
expect_argv "20m" argv-ios
|
||||||
expect_argv "iPhone 16 Pro" argv-ios
|
expect_argv "iPhone 17 Pro" argv-ios
|
||||||
|
|
||||||
run argv-android android 2 <<TRACE
|
run argv-android android 2 <<TRACE
|
||||||
$on_txn
|
$on_txn
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ case "$platform" in
|
|||||||
# away from the `simctl uninstall` + `install` path that races FrontBoard
|
# away from the `simctl uninstall` + `install` path that races FrontBoard
|
||||||
# ("app.folio is unknown to FrontBoard"), which needs an app path to reach.
|
# ("app.folio is unknown to FrontBoard"), which needs an app path to reach.
|
||||||
folio_args+=(--platform ios
|
folio_args+=(--platform ios
|
||||||
--ios-device "${IOS_DEVICE:-iPhone 16 Pro}")
|
--ios-device "${IOS_DEVICE:-iPhone 17 Pro}")
|
||||||
;;
|
;;
|
||||||
web)
|
web)
|
||||||
dist="examples/folio/app/webApp/build/dist/wasmJs/developmentExecutable"
|
dist="examples/folio/app/webApp/build/dist/wasmJs/developmentExecutable"
|
||||||
|
|||||||
+77
-26
@@ -51,17 +51,17 @@ jobs:
|
|||||||
- name: Set up Android SDK
|
- name: Set up Android SDK
|
||||||
uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4.0.1
|
uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4.0.1
|
||||||
|
|
||||||
- name: Set up Node 22
|
- name: Set up Node 24
|
||||||
uses: actions/setup-node@v7
|
uses: actions/setup-node@v7
|
||||||
with:
|
with:
|
||||||
node-version: "22"
|
node-version: "24"
|
||||||
cache: npm
|
cache: npm
|
||||||
cache-dependency-path: pkg/spec/package-lock.json
|
cache-dependency-path: pkg/spec/package-lock.json
|
||||||
|
|
||||||
- name: Set up bun
|
- name: Set up bun
|
||||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
||||||
with:
|
with:
|
||||||
bun-version: "1.3.13"
|
bun-version: "1.3.14"
|
||||||
|
|
||||||
- name: Cache bun store
|
- name: Cache bun store
|
||||||
uses: actions/cache@v6
|
uses: actions/cache@v6
|
||||||
@@ -74,18 +74,26 @@ jobs:
|
|||||||
# The token is what stops this step flaking: without it the action pulls
|
# The token is what stops this step flaking: without it the action pulls
|
||||||
# buf's release tarball from github.com anonymously, on the shared runner
|
# buf's release tarball from github.com anonymously, on the shared runner
|
||||||
# IP's rate limit, and a throttled connection shows up as `socket hang
|
# IP's rate limit, and a throttled connection shows up as `socket hang
|
||||||
# up` after three retries. The version is the action's own default, made
|
# up` after three retries. The version is pinned explicitly so a new
|
||||||
# explicit so a new action release cannot move the buf we build with.
|
# action release cannot move the buf we build with. `setup_only` is what
|
||||||
|
# keeps this a plain install: left off, the action runs its own lint,
|
||||||
|
# format and breaking checks, and `buf lint` below is where this repo
|
||||||
|
# says which rules it wants.
|
||||||
- name: Install buf
|
- name: Install buf
|
||||||
uses: bufbuild/buf-setup-action@a47c93e0b1648d5651a065437926377d060baa99 # v1.50.0
|
uses: bufbuild/buf-action@8c6a16e16f12ba20b6470afa9c2ba9b5ba8c97c3 # v1.5.0
|
||||||
with:
|
with:
|
||||||
version: "1.50.0"
|
version: "1.72.0"
|
||||||
|
setup_only: true
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
# Pinned, not @latest: these two write the committed stubs, so a floating
|
||||||
|
# version is an unreviewed input to generated code. The versions are the
|
||||||
|
# ones the stubs under proto/ record generating them, so what CI builds
|
||||||
|
# with and what is checked in stay the same thing.
|
||||||
- name: Install protoc plugins
|
- name: Install protoc plugins
|
||||||
run: |
|
run: |
|
||||||
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.11
|
||||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.6.0
|
||||||
echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"
|
echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"
|
||||||
|
|
||||||
- name: Cache Gradle
|
- name: Cache Gradle
|
||||||
@@ -198,7 +206,7 @@ jobs:
|
|||||||
- name: Set up bun
|
- name: Set up bun
|
||||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
||||||
with:
|
with:
|
||||||
bun-version: "1.3.13"
|
bun-version: "1.3.14"
|
||||||
|
|
||||||
- name: Build the folio app
|
- name: Build the folio app
|
||||||
uses: ./.github/actions/folio-app
|
uses: ./.github/actions/folio-app
|
||||||
@@ -228,13 +236,14 @@ jobs:
|
|||||||
|
|
||||||
folio-ios:
|
folio-ios:
|
||||||
name: Folio (ios)
|
name: Folio (ios)
|
||||||
runs-on: macos-15
|
runs-on: macos-26
|
||||||
timeout-minutes: 90
|
timeout-minutes: 90
|
||||||
env:
|
env:
|
||||||
SEED: "7"
|
SEED: "7"
|
||||||
MAX_STEPS: "240"
|
MAX_STEPS: "240"
|
||||||
DURATION: 20m
|
DURATION: 20m
|
||||||
IOS_DEVICE: iPhone 16 Pro
|
IOS_DEVICE: iPhone 17 Pro
|
||||||
|
IOS_RUNTIME: iOS 26.2
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v7
|
- uses: actions/checkout@v7
|
||||||
|
|
||||||
@@ -247,7 +256,7 @@ jobs:
|
|||||||
- name: Set up bun
|
- name: Set up bun
|
||||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
||||||
with:
|
with:
|
||||||
bun-version: "1.3.13"
|
bun-version: "1.3.14"
|
||||||
|
|
||||||
- name: Build the folio app
|
- name: Build the folio app
|
||||||
uses: ./.github/actions/folio-app
|
uses: ./.github/actions/folio-app
|
||||||
@@ -257,10 +266,53 @@ jobs:
|
|||||||
- name: Build sanderling
|
- name: Build sanderling
|
||||||
run: make sanderling-ios
|
run: make sanderling-ios
|
||||||
|
|
||||||
|
# simctl resolves a device by name alone, and one image carries the same
|
||||||
|
# phone under several runtimes: iPhone 17 Pro exists here on iOS 26.2,
|
||||||
|
# 26.4 and 26.5. Booting by name is therefore booting on whichever one
|
||||||
|
# simctl happens to list first, and a seed only means something against a
|
||||||
|
# fixed runtime. So the pair is resolved to a UDID here and every step
|
||||||
|
# after this boots that one simulator. An image that stops carrying the
|
||||||
|
# pair fails here naming what it does carry, rather than as a
|
||||||
|
# `bootstatus` error to read backwards from.
|
||||||
|
#
|
||||||
|
# The UDID stays in this step. IOS_DEVICE has to keep holding the name,
|
||||||
|
# because `just ios` spends it as xcodebuild's `-destination name=`, which
|
||||||
|
# matches on the display name and rejects a UDID. Nothing downstream needs
|
||||||
|
# it anyway: the install, the launch and the terminate all address
|
||||||
|
# `booted`, and sanderling resolves --ios-device against booted simulators
|
||||||
|
# before available ones, so the one booted here is the one they all get.
|
||||||
- name: Boot a simulator
|
- name: Boot a simulator
|
||||||
run: |
|
run: |
|
||||||
xcrun simctl boot "$IOS_DEVICE" || true
|
udid="$(python3 <<'PY'
|
||||||
xcrun simctl bootstatus "$IOS_DEVICE" -b
|
import json, os, subprocess, sys
|
||||||
|
|
||||||
|
want_device = os.environ["IOS_DEVICE"]
|
||||||
|
want_runtime = os.environ["IOS_RUNTIME"]
|
||||||
|
devices = json.loads(subprocess.run(
|
||||||
|
["xcrun", "simctl", "list", "devices", "available", "--json"],
|
||||||
|
capture_output=True, text=True, check=True).stdout)["devices"]
|
||||||
|
|
||||||
|
def name_of(runtime):
|
||||||
|
family, _, version = runtime.rsplit(".", 1)[-1].partition("-")
|
||||||
|
return "%s %s" % (family, version.replace("-", "."))
|
||||||
|
|
||||||
|
for runtime, entries in devices.items():
|
||||||
|
if name_of(runtime) != want_runtime:
|
||||||
|
continue
|
||||||
|
for entry in entries:
|
||||||
|
if entry["name"] == want_device:
|
||||||
|
print(entry["udid"])
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
carried = sorted({"%s on %s" % (e["name"], name_of(r))
|
||||||
|
for r, es in devices.items() for e in es})
|
||||||
|
sys.exit("no %r on %r in this image. it carries:\n %s"
|
||||||
|
% (want_device, want_runtime, "\n ".join(carried) or "no simulators at all"))
|
||||||
|
PY
|
||||||
|
)"
|
||||||
|
echo "booting $IOS_DEVICE on $IOS_RUNTIME ($udid)"
|
||||||
|
xcrun simctl boot "$udid"
|
||||||
|
xcrun simctl bootstatus "$udid" -b
|
||||||
|
|
||||||
- name: Build and install folio
|
- name: Build and install folio
|
||||||
working-directory: examples/folio
|
working-directory: examples/folio
|
||||||
@@ -302,7 +354,7 @@ jobs:
|
|||||||
- name: Set up bun
|
- name: Set up bun
|
||||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
||||||
with:
|
with:
|
||||||
bun-version: "1.3.13"
|
bun-version: "1.3.14"
|
||||||
|
|
||||||
- name: Set up headless Chrome
|
- name: Set up headless Chrome
|
||||||
uses: ./.github/actions/headless-chrome
|
uses: ./.github/actions/headless-chrome
|
||||||
@@ -359,7 +411,7 @@ jobs:
|
|||||||
- name: Set up bun
|
- name: Set up bun
|
||||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
||||||
with:
|
with:
|
||||||
bun-version: "1.3.13"
|
bun-version: "1.3.14"
|
||||||
|
|
||||||
- name: Set up headless Chrome
|
- name: Set up headless Chrome
|
||||||
uses: ./.github/actions/headless-chrome
|
uses: ./.github/actions/headless-chrome
|
||||||
@@ -517,21 +569,20 @@ jobs:
|
|||||||
# this job needs the git credential afterwards.
|
# this job needs the git credential afterwards.
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Set up Node 22
|
# registry-url below writes an `_authToken=${NODE_AUTH_TOKEN}` line into
|
||||||
|
# .npmrc whether or not a token exists, and an npm older than 11.5.1 reads
|
||||||
|
# that empty line as "auth is configured" and never asks for an OIDC
|
||||||
|
# token, so the publish fails needing auth. 24 is the oldest Node whose
|
||||||
|
# bundled npm clears that floor (11.17.0), which is why it is pinned here
|
||||||
|
# rather than upgrading npm over the top of an older one.
|
||||||
|
- name: Set up Node 24
|
||||||
uses: actions/setup-node@v7
|
uses: actions/setup-node@v7
|
||||||
with:
|
with:
|
||||||
node-version: "22"
|
node-version: "24"
|
||||||
registry-url: "https://registry.npmjs.org"
|
registry-url: "https://registry.npmjs.org"
|
||||||
cache: npm
|
cache: npm
|
||||||
cache-dependency-path: pkg/spec/package-lock.json
|
cache-dependency-path: pkg/spec/package-lock.json
|
||||||
|
|
||||||
# registry-url above writes an `_authToken=${NODE_AUTH_TOKEN}` line into
|
|
||||||
# .npmrc whether or not a token exists, and an npm older than 11.5.1 reads
|
|
||||||
# that empty line as "auth is configured" and never asks for an OIDC
|
|
||||||
# token, so the publish fails needing auth. Node 22 ships npm 10.
|
|
||||||
- name: Install an npm that can publish over OIDC
|
|
||||||
run: npm install -g npm@latest
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
working-directory: pkg/spec
|
working-directory: pkg/spec
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|||||||
@@ -170,6 +170,14 @@ reinstall-and-launch cycles on iOS 26.1, 10 of them reinstalling on top of a
|
|||||||
live app, so any fix for it has to be developed on a host that can still show it
|
live app, so any fix for it has to be developed on a host that can still show it
|
||||||
failing.
|
failing.
|
||||||
|
|
||||||
|
The leg names a device and a runtime, `iPhone 17 Pro` on `iOS 26.2`, and boots
|
||||||
|
by the UDID that pair resolves to. Both halves matter: one runner image carries
|
||||||
|
the same phone under several runtimes, so booting by name alone is booting on
|
||||||
|
whichever one `simctl` lists first, and a seed that is only calibrated against a
|
||||||
|
runtime it did not run on says nothing. A runner image that stops carrying the
|
||||||
|
pair fails the boot step naming what it does carry, which is the cue to pick a
|
||||||
|
new pair and recalibrate rather than a `bootstatus` error to read backwards.
|
||||||
|
|
||||||
Only one sanderling run may drive a given simulator at a time. The driver takes
|
Only one sanderling run may drive a given simulator at a time. The driver takes
|
||||||
an advisory lock on the target's UDID and a second run is refused with the lock
|
an advisory lock on the target's UDID and a second run is refused with the lock
|
||||||
path in the message, because two runs interleaving app lifecycle leave the first
|
path in the message, because two runs interleaving app lifecycle leave the first
|
||||||
|
|||||||
Reference in new issue
Block a user