155 lines
6.3 KiB
YAML
155 lines
6.3 KiB
YAML
name: PR Checks
|
|
|
|
on:
|
|
pull_request:
|
|
types:
|
|
- opened
|
|
- synchronize
|
|
- reopened
|
|
- ready_for_review
|
|
|
|
jobs:
|
|
verify:
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Install native build tools
|
|
run: sudo apt-get update && sudo apt-get install -y build-essential python3 zlib1g-dev zsh
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version-file: package.json
|
|
|
|
- name: Setup pnpm
|
|
uses: pnpm/action-setup@v6
|
|
with:
|
|
run_install: false
|
|
|
|
# Why: pnpm's bundled node-gyp ships gyp_main.py without execute
|
|
# permission, which breaks native module builds (e.g. node-pty's
|
|
# postinstall) with "/bin/sh: gyp_main.py: Permission denied".
|
|
# Pin the fallback to the lockfile's node-gyp version so CI stays
|
|
# reproducible while forcing pnpm to bypass its broken bundled copy.
|
|
# Gate on runner.os == 'Linux' to match release.yml — the
|
|
# npm-global path layout this step assumes is POSIX-shaped, and the
|
|
# failure has only been observed on Linux runners. Today this job
|
|
# pins runs-on: ubuntu-latest so the guard is a no-op, but it
|
|
# prevents a silent break if a Windows/macOS matrix is added later.
|
|
- name: Use external node-gyp to avoid pnpm's bundled copy (Linux only)
|
|
if: runner.os == 'Linux'
|
|
run: |
|
|
npm install -g node-gyp@11.5.0
|
|
echo "npm_config_node_gyp=$(npm root -g)/node-gyp/bin/node-gyp.js" >> "$GITHUB_ENV"
|
|
|
|
- name: Prepare dependency install
|
|
run: |
|
|
if [ -e node_modules ]; then
|
|
ls -ld node_modules
|
|
rm -rf node_modules
|
|
fi
|
|
|
|
- name: Install dependencies
|
|
# Why: pnpm 10.24's frozen headless fast path can fail on fresh Ubuntu
|
|
# runners while creating the root node_modules. Use the normal resolver
|
|
# path, then verify package metadata stayed unchanged.
|
|
run: |
|
|
pnpm install --no-frozen-lockfile --prefer-frozen-lockfile=false
|
|
git diff --exit-code package.json pnpm-lock.yaml
|
|
|
|
- name: Lint
|
|
run: pnpm exec oxlint --format github
|
|
|
|
- name: Check styled scrollbars
|
|
run: pnpm check:styled-scrollbars
|
|
|
|
- name: Check reliability gate manifest
|
|
run: pnpm run check:reliability-gates
|
|
|
|
# Why: oxlint fails any file over max-lines that is NOT suppressed, so this
|
|
# ratchet forbids ADDING a new suppression (inline disable or mobile max
|
|
# bump). Existing oversized files are grandfathered in
|
|
# config/max-lines-baseline.txt, which may only shrink — new bypasses fail
|
|
# here with a clear message instead of silently growing the debt.
|
|
- name: Enforce max-lines ratchet (no new bypasses)
|
|
run: pnpm run check:max-lines-ratchet
|
|
|
|
# Why: project-owned type declarations must live in .ts so tsc
|
|
# actually checks them. TypeScript's skipLibCheck: true (inherited
|
|
# from @electron-toolkit/tsconfig) silently widens unresolved names
|
|
# in .d.ts to `any`, which is how #1186 shipped a broken IPC signature
|
|
# past typecheck. See docs/preload-typecheck-hole.md.
|
|
- name: Guard against project-owned .d.ts in preload/shared
|
|
run: |
|
|
matches=$(find src/preload src/shared -name '*.d.ts' 2>/dev/null || true)
|
|
if [ -n "$matches" ]; then
|
|
echo "::error::Project-owned .d.ts files are not allowed under src/preload or src/shared."
|
|
echo "Move type declarations into a .ts file so skipLibCheck does not hide errors."
|
|
echo "See docs/preload-typecheck-hole.md."
|
|
echo "Found:"
|
|
echo "$matches"
|
|
exit 1
|
|
fi
|
|
|
|
- name: Check feature wall asset budget
|
|
run: pnpm check:feature-wall-assets
|
|
|
|
- name: Verify macOS entitlements
|
|
run: pnpm verify:macos-entitlements
|
|
|
|
- name: Typecheck
|
|
run: pnpm typecheck
|
|
|
|
# Why: real old Git diagnostics differ from mocked errors. Keep the
|
|
# fallback predicates executable across the baseline, transition, and
|
|
# current command shapes so a newly added flag cannot silently regress.
|
|
- name: Verify Git binary compatibility matrix
|
|
run: |
|
|
archive="$RUNNER_TEMP/git-2.25.5.tar.gz"
|
|
source="$RUNNER_TEMP/git-2.25.5"
|
|
curl -fsSL https://www.kernel.org/pub/software/scm/git/git-2.25.5.tar.gz -o "$archive"
|
|
echo "41662c52fc16fec4963bfc41075e71f8ead6b5e386797eb6f9a1111ff95a8ddf $archive" \
|
|
| sha256sum --check
|
|
mkdir -p "$source"
|
|
tar -xzf "$archive" -C "$source" --strip-components=1
|
|
make -C "$source" -j2 NO_GETTEXT=YesPlease NO_TCLTK=YesPlease NO_PYTHON=YesPlease git
|
|
ORCA_GIT_COMPAT_BINARY="$source/git" ORCA_GIT_COMPAT_VERSION="2.25.5" \
|
|
pnpm exec vitest run --config config/vitest.config.ts \
|
|
src/shared/git-binary-compatibility.test.ts
|
|
|
|
for spec in \
|
|
"alpine/git:edge-2.38.1|2.38.1" \
|
|
"alpine/git:v2.49.1|2.49.1"; do
|
|
image="${spec%%|*}"
|
|
version="${spec#*|}"
|
|
ORCA_GIT_COMPAT_IMAGE="$image" ORCA_GIT_COMPAT_VERSION="$version" \
|
|
pnpm exec vitest run --config config/vitest.config.ts \
|
|
src/shared/git-binary-compatibility.test.ts
|
|
done
|
|
|
|
# Why: postinstall rebuilds better-sqlite3 for Electron's ABI via
|
|
# @electron/rebuild, but vitest runs under system Node.js. Rebuild
|
|
# it for Node so orchestration tests can load the native module.
|
|
- name: Rebuild better-sqlite3 for Node
|
|
run: pnpm rebuild better-sqlite3
|
|
|
|
# Why: install intentionally blocks Electron's package postinstall, but
|
|
# some unit tests import `electron` under Node and require path.txt.
|
|
- name: Install Electron package binary for tests
|
|
run: node config/scripts/install-electron-package-binary.mjs
|
|
|
|
- name: Test
|
|
run: pnpm test
|
|
|
|
- name: Build unpacked app
|
|
run: pnpm build:unpack
|
|
|
|
# Why: the packaged CLI runs outside Electron's asar integration, so
|
|
# bare runtime imports must be present in the package itself. Run from a
|
|
# temp copy so Node cannot mask missing package deps with repo node_modules.
|
|
- name: Smoke packaged CLI
|
|
run: node config/scripts/smoke-packaged-cli.mjs --app-dir=dist/linux-unpacked
|