Builder's Manual · Night Arcade Cabinet
CI/CD Pipeline
Source-backed guides to the speed curve, ReactLynx architecture, sprites, native hosts, documentation site, and release pipeline.
CI/CD Pipeline
All automation runs on GitHub Actions. Workflows are in .github/workflows/.
Workflow Overview
| Workflow | File | Trigger | Description |
|---|---|---|---|
| Build Check | ci.yml |
Manual, push to main/lynx-migration, PR to main |
Audit dependencies, check bundles/web host/docs, validate site links/metadata, compile/lint Android, verify APK bundle |
| CodeQL | codeql.yml |
Push/PR to main, weekly, manual |
JavaScript/TypeScript and Actions security analysis |
| Deploy Web | deploy.yml |
Push to main, manual |
Build and deploy the Astro docs/ site to GitHub Pages via the shared Pages workflow |
| Build Android | build-android.yml |
Push to main, manual from main |
Read-only build/signing job followed by a separate build-release publisher |
| Build iOS | build-ios.yml |
v* tags, manual |
Skip without an Xcode project; otherwise build an unsigned archive |
| Release | release.yml |
v* tags, manual |
Full release pipeline with all artifacts |
Build Check
Runs on manual dispatch, pushes to main/lynx-migration, and pull requests targeting main. Validates the codebase compiles and builds:
bun install --frozen-lockfile— install dependenciesbun audit— fail on known dependency advisoriesbun run check— TypeScript type-checkingbun run buildandbun run build:web-host— build Lynx/web bundles and the development host- Upload bundles as artifact (14-day retention)
- Compile and lint the Android debug host in a read-only job without signing secrets, then verify the APK contains the current bundle
- Install the frozen docs lockfile, audit it, build the site, and check every generated page’s local links, fragments, unique IDs, and canonical/OG URL
Gameplay unit tests, browser UI tests, and JavaScript lint/format checks are not configured. Successful builds and static checks do not establish device behavior or accessibility conformance.
Deploy Web
Deploys the Astro site in docs/ to GitHub Pages on pushes to main or manual dispatch from main. The repository calls jonathanperis/.github/.github/workflows/pages-docs-deploy.yml at the full commit SHA recorded in deploy.yml. Only the optional public analytics ID is passed as a secret. The shared workflow installs frozen dependencies, uses Node.js 22 for Astro 7, builds the docs site, and publishes the static output.
Build Android
The main production workflow. On every push to main:
- Version computation — from the short SHA (
0.0.0-a1b2c3d) - Build Lynx bundle —
bun run build - Stage bundle — Gradle copies the current
dist/main.lynx.bundleinto generated APK assets - Decode keystore when configured — from
KEYSTORE_BASE64secret - Gradle build and package verification —
./gradlew assembleRelease, signed only when the signing env vars are present; verify that the APK contains the exact current bundle - Artifact handoff — upload the versioned APK from the read-only build job
- Immutable publication — a separate write-enabled job creates
build/<version>at the verified commit, uploads the APK to a draft, then publishes it
Android Signing Secrets
| Secret | Purpose |
|---|---|
KEYSTORE_BASE64 |
Base64-encoded release keystore |
KEYSTORE_PASSWORD |
Keystore password |
KEY_ALIAS |
Key alias name |
KEY_PASSWORD |
Key password |
Android Artifact Matrix
| Artifact | Trigger/path | Signing/status |
|---|---|---|
| Local debug APK | cd android && ./gradlew assembleDebug after the root bundle build |
Debug-signed by Android tooling |
| CI main-build APK | build-android.yml on push to main or manual dispatch |
Release build; signed only when keystore secrets are configured |
| Tagged release APK | release.yml on v* tags |
Attached to the GitHub Release; signed when KEYSTORE_BASE64, KEYSTORE_PASSWORD, KEY_ALIAS, and KEY_PASSWORD are present |
Versioning
| Trigger | Version Name | Version Code | Release Type |
|---|---|---|---|
Push to main |
0.0.0-<sha> |
Epoch-based | Automated build release (build/<version> tag) |
Tag v1.2.3 |
1.2.3 |
Epoch-based | Full release |
Build iOS
Scaffolded but requires manual setup:
- Create and track an Xcode project with a shared
SpeedyBirdscheme (see Native Host Apps). - Build/package the bundle and install the locked Ruby/CocoaPods dependencies.
- Build an unsigned archive. Paid membership is not needed for this operation.
The checked-in ios/ directory contains a Swift/CocoaPods scaffold, not a generated .xcodeproj. The workflows always disable code signing; Apple secrets are not read. Signed device distribution would require additional workflow implementation as well as Apple signing assets. Dependency resolution alone is not an app/archive build.
Release
Triggered by version tags (v*) or manual dispatch from main or a version tag. This is the sole publisher for versioned releases, avoiding concurrent publishers racing an immutable release. Builds Lynx bundles and conditionally builds Android/iOS when their native projects exist; a failed build blocks publication. The publishing job uploads all available assets to a draft, then publishes the immutable release. Subsequent corrections require a new release instead of replacing published assets.