Files
Folo/.github/scripts/release-workflow-guards.test.ts
DIYgod 28ab52296e fix(mobile): embed the real OTA runtime version in Android builds
EAS generates android/ with `expo prebuild`, which sets NODE_ENV to
"development" when it is unset. The app config picked the 0.0.0-dev
runtime from NODE_ENV, so every Android binary since the React Native
0.79 upgrade embedded expo_runtime_version 0.0.0-dev, and ota.folo.is
rejects its update checks. iOS kept the real runtime because eas-cli
syncs its committed Expo.plist outside of prebuild.

Decide the development runtime from the EAS build profile and fall back
to NODE_ENV only without one (expo start, local prebuild). The
eas-build-post-install hook now fails any build whose native runtime
differs from the expected one, and a test evaluates every eas.json
profile the way prebuild does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 16:21:11 +08:00

50 lines
2.1 KiB
TypeScript

import { readFileSync } from "node:fs"
import { describe, expect, it } from "vitest"
const workflow = (name: string) =>
readFileSync(new URL(`../workflows/${name}`, import.meta.url), "utf8")
describe("release build workflow guards", () => {
it("skips direct mobile push builds for desktop release commits on main", () => {
const androidWorkflow = workflow("build-android.yml")
const iosWorkflow = workflow("build-ios.yml")
expect(androidWorkflow).toContain("github.ref == 'refs/heads/main'")
expect(androidWorkflow).toContain("release(desktop):")
expect(iosWorkflow).toContain("github.ref == 'refs/heads/main'")
expect(iosWorkflow).toContain("release(desktop):")
})
// Android builds once shipped the 0.0.0-dev runtime unnoticed, so every EAS build checks it.
it("verifies the native OTA runtime version in every EAS mobile build", () => {
const mobilePackage = JSON.parse(
readFileSync(new URL("../../apps/mobile/package.json", import.meta.url), "utf8"),
) as { scripts: Record<string, string> }
expect(mobilePackage.scripts["eas-build-post-install"]).toContain(
"scripts/verify-native-runtime-version.ts",
)
})
it("skips direct desktop push builds for mobile release commits on mobile-main", () => {
const desktopWorkflow = workflow("build-desktop.yml")
expect(desktopWorkflow).toContain("github.ref == 'refs/heads/mobile-main'")
expect(desktopWorkflow).toContain("release(mobile):")
})
// The sync PRs that merge main and mobile-main back into dev are opened with GITHUB_TOKEN, which
// starts no pull_request workflows. Their auto-merge waits for dev's required checks, so those
// checks have to run on pushes to both release branches.
it("runs dev's required checks on pushes to both release branches", () => {
for (const name of ["lint.yml", "build-web.yml"]) {
const pushBranches = workflow(name).match(/^ {2}push:\n {4}branches: \[([^\]]*)\]$/m)?.[1]
const branches = pushBranches?.split(",").map((branch) => branch.trim())
expect(branches).toEqual(expect.arrayContaining(["main", "dev", "mobile-main"]))
}
})
})