Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions .github/actions/setup-workspace/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ inputs:
description: Node version to install
required: true
pnpm-version:
description: pnpm version to install
description: pnpm version to install. Needs a matching pnpm-<version>.sha256 file beside this action.
required: true
cache-prefix:
description: Names this job's Turbo cache entry (e.g. checks, test-server). Every job reads every prefix; this only decides which entry the job writes back.
Expand All @@ -19,11 +19,15 @@ inputs:
runs:
using: composite
steps:
# A pinned release binary instead of pnpm/action-setup: the action
# bootstraps through `npm ci` and `pnpm self-update`, two npm registry
# round trips that cost 30 s at best and stalled for 7 minutes on every
# job of a run when the registry was slow. See install-pnpm.sh.
- name: Set up pnpm
uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
with:
version: ${{ inputs.pnpm-version }}
run_install: false
shell: bash
env:
PNPM_VERSION: ${{ inputs.pnpm-version }}
run: bash "${GITHUB_ACTION_PATH}/install-pnpm.sh"

- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
Expand Down
63 changes: 63 additions & 0 deletions .github/actions/setup-workspace/install-pnpm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env bash
# Installs the pinned pnpm release binary straight from GitHub Releases.
#
# pnpm/action-setup bootstraps pnpm with `npm ci` against the npm registry and
# then runs `pnpm self-update`, so every job paid two registry round trips
# before doing any work: 30 s on a good day, and 7 minutes on the runs where
# the registry stalled (the same stall hit every job of the run at once). A
# GitHub release asset is a single download from the CDN the runner already
# talks to for checkout, and the pinned sha256 gives the same integrity the
# action's committed lockfile did.
set -euo pipefail

version="${PNPM_VERSION:?PNPM_VERSION is required}"
action_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
checksums="${action_dir}/pnpm-${version}.sha256"

if [[ ! -f "${checksums}" ]]; then
echo "::error::No checksums for pnpm ${version}. Download the release assets from https://github.com/pnpm/pnpm/releases/tag/v${version}, run sha256sum on them, and commit the output as ${checksums}."
exit 1
fi

case "$(uname -s)-$(uname -m)" in
Linux-x86_64) asset="pnpm-linux-x64" ;;
Linux-aarch64 | Linux-arm64) asset="pnpm-linux-arm64" ;;
Darwin-arm64) asset="pnpm-macos-arm64" ;;
Darwin-x86_64) asset="pnpm-macos-x64" ;;
*)
echo "::error::Unsupported runner platform $(uname -s)-$(uname -m) for the pnpm release binary."
exit 1
;;
esac

expected="$(awk -v asset="${asset}" '$2 == asset { print $1 }' "${checksums}")"
if [[ -z "${expected}" ]]; then
echo "::error::${checksums} has no entry for ${asset}."
exit 1
fi

install_dir="${RUNNER_TEMP:-/tmp}/pnpm-${version}"
mkdir -p "${install_dir}/bin"
binary="${install_dir}/bin/pnpm"

url="https://github.com/pnpm/pnpm/releases/download/v${version}/${asset}"
curl --fail --silent --show-error --location \
--retry 5 --retry-all-errors --retry-delay 2 \
--connect-timeout 15 --max-time 180 \
--output "${binary}" "${url}"

if command -v sha256sum >/dev/null 2>&1; then
actual="$(sha256sum "${binary}" | awk '{ print $1 }')"
else
actual="$(shasum -a 256 "${binary}" | awk '{ print $1 }')"
fi
if [[ "${actual}" != "${expected}" ]]; then
echo "::error::sha256 mismatch for ${asset}: expected ${expected}, got ${actual}."
exit 1
fi

chmod +x "${binary}"
ln -sf pnpm "${install_dir}/bin/pnpx"
echo "${install_dir}/bin" >> "${GITHUB_PATH}"
echo "PNPM_HOME=${install_dir}/bin" >> "${GITHUB_ENV}"
echo "Installed pnpm $("${binary}" --version) from ${url}"
4 changes: 4 additions & 0 deletions .github/actions/setup-workspace/pnpm-9.15.0.sha256
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
1f66770efc74835602642c37b8d31c635c0a90bdfc1401c273c6e957714b7561 pnpm-linux-arm64
f389709623d29195c5555a32513d633d28aa457c30448d0bb8d87439c7b127dc pnpm-linux-x64
cfc80f4a44d0d2e7bb581d5ee8436933df5f1d10794349eb52029c71c48534cb pnpm-macos-arm64
c7f3ee5213019219303fd657197e63ccac292dc487f895f7d885cf1986a5add8 pnpm-macos-x64
137 changes: 89 additions & 48 deletions packages/bb-app/scripts/smoke-tarball.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,21 @@ const smokeProcessEnv = {
BB_TELEMETRY: "false",
};

function formatElapsed(startedAt) {
return `${((performance.now() - startedAt) / 1000).toFixed(1)}s`;
}

async function timed(label, run) {
const startedAt = performance.now();
try {
return await run();
} finally {
process.stdout.write(
`bb-app tarball smoke: ${label} ${formatElapsed(startedAt)}\n`,
);
}
}

function delay(ms) {
return new Promise((resolvePromise) => {
setTimeout(resolvePromise, ms);
Expand Down Expand Up @@ -287,11 +302,22 @@ async function smokeNpxEntrypoint(tarballPath) {
// Keep one real invocation through the package's advertised npx path. Once
// npx dispatches the bin, the installed-package smokes below cover the same
// launcher without repeatedly charging npm startup to readiness budgets.
await runCommand({
args: ["--yes", "--package", tarballPath, "--", "bb-app", "--help"],
command: "npx",
label: "bb-app npx help",
});
await timed("npx install and help", () =>
runCommand({
args: [
"--yes",
"--no-audit",
"--no-fund",
"--package",
tarballPath,
"--",
"bb-app",
"--help",
],
command: "npx",
label: "bb-app npx help",
}),
);
}

async function packTarball() {
Expand Down Expand Up @@ -796,18 +822,20 @@ async function smokeSdkPackage(tarballPath) {
join(sdkDir, "package.json"),
JSON.stringify({ type: "module", private: true }, null, 2),
);
await runCommand({
args: [
"install",
"--ignore-scripts=false",
"--no-audit",
"--no-fund",
tarballPath,
],
command: "npm",
cwd: sdkDir,
label: "install bb-app SDK smoke package",
});
await timed("npm install tarball", () =>
runCommand({
args: [
"install",
"--ignore-scripts=false",
"--no-audit",
"--no-fund",
tarballPath,
],
command: "npm",
cwd: sdkDir,
label: "install bb-app SDK smoke package",
}),
);
await runCommand({
args: [
"--input-type=module",
Expand All @@ -830,26 +858,30 @@ async function smokeSdkPackage(tarballPath) {
"",
].join("\n"),
);
await runCommand({
args: [
"--yes",
"--package",
"typescript",
"--",
"tsc",
"--module",
"NodeNext",
"--moduleResolution",
"NodeNext",
"--target",
"ES2022",
"--noEmit",
"sdk-smoke.ts",
],
command: "npx",
cwd: sdkDir,
label: "bb-app SDK TypeScript import",
});
await timed("npx typescript check", () =>
runCommand({
args: [
"--yes",
"--no-audit",
"--no-fund",
"--package",
"typescript",
"--",
"tsc",
"--module",
"NodeNext",
"--moduleResolution",
"NodeNext",
"--target",
"ES2022",
"--noEmit",
"sdk-smoke.ts",
],
command: "npx",
cwd: sdkDir,
label: "bb-app SDK TypeScript import",
}),
);
return sdkDir;
}

Expand Down Expand Up @@ -1096,19 +1128,28 @@ async function smokeDaemonJoin(binDir) {
}

try {
const tarballPath = await packTarball();
await smokeNpxEntrypoint(tarballPath);
const sdkDir = await smokeSdkPackage(tarballPath);
const smokeStartedAt = performance.now();
const tarballPath = await timed("npm pack", () => packTarball());
await timed("npx entrypoint", () => smokeNpxEntrypoint(tarballPath));
const sdkDir = await timed("sdk package", () => smokeSdkPackage(tarballPath));
const installedBinDir = join(sdkDir, "node_modules", ".bin");
const installedPackageDir = join(sdkDir, "node_modules", "bb-app");
await smokeHelpCommands(installedBinDir);
await smokeConfigCommand(installedBinDir);
await smokeInstalledRepack(installedPackageDir);
await smokeProviderBridgeBundles(installedPackageDir);
await smokePluginHostWorkerBundle(installedPackageDir);
await smokeFullStack(installedBinDir, sdkDir);
await smokeDaemonJoin(installedBinDir);
process.stdout.write("bb-app tarball smoke passed\n");
await timed("help commands", () => smokeHelpCommands(installedBinDir));
await timed("config command", () => smokeConfigCommand(installedBinDir));
await timed("installed repack", () =>
smokeInstalledRepack(installedPackageDir),
);
await timed("provider bridge bundles", () =>
smokeProviderBridgeBundles(installedPackageDir),
);
await timed("plugin host worker bundle", () =>
smokePluginHostWorkerBundle(installedPackageDir),
);
await timed("full stack", () => smokeFullStack(installedBinDir, sdkDir));
await timed("daemon join", () => smokeDaemonJoin(installedBinDir));
process.stdout.write(
`bb-app tarball smoke passed in ${formatElapsed(smokeStartedAt)}\n`,
);
} finally {
await rm(tempRoot, { force: true, recursive: true });
}
Loading