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
5 changes: 5 additions & 0 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env sh
set -eu

echo "Running BRIGX pre-CI checks before push..."
npm run verify:ci
25 changes: 3 additions & 22 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ on:
branches:
- master
paths-ignore:
- 'package.json'
- '*.md'

jobs:
Expand All @@ -31,26 +30,8 @@ jobs:
- name: Install npm dependencies
run: npm ci

- name: Type-check
run: pixi run npx tsc --noEmit

- name: Lint
run: pixi run npm run lint

- name: Architecture guardrails
run: pixi run npm run quality:architecture

- name: Licence policy
run: pixi run npm run quality:licenses

- name: Runtime and build dependency audit
run: pixi run npm run quality:security

- name: Unit tests
run: pixi run npm test

- name: Production build
run: pixi run npm run build
- name: Run core CI checks
run: pixi run npm run verify:ci:core

browser:
name: Browser end-to-end tests
Expand All @@ -70,4 +51,4 @@ jobs:
run: npx playwright install --with-deps chromium

- name: Browser tests
run: npm run test:e2e
run: npm run verify:ci:browser
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
legacy-peer-deps=true
engine-strict=true
36 changes: 30 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,14 @@ Thank you for your interest in contributing to BRIGx — a browser-based tool fo
2. **Install dependencies**

```bash
npm install
nvm use
npm ci
npx playwright install chromium
```

`npm ci` also installs the repository's pre-push hook. The hook runs the
same checks as GitHub CI and cancels the push if any of them fail.

3. **Start the development server**

```bash
Expand All @@ -31,6 +36,25 @@ Thank you for your interest in contributing to BRIGx — a browser-based tool fo

The app will be available at [http://localhost:3000](http://localhost:3000). Changes to source files are reflected immediately via hot reload.

## Checking a Change Before CI

Run the exact checks used by GitHub CI:

```bash
npm run verify:ci
```

This includes type-checking, linting, architecture and licence policies, the
dependency security audit, unit tests, the production build, and production
browser tests. `npm run verify` additionally exercises the development server.

The pre-push hook runs `npm run verify:ci` automatically. If hooks were disabled
or this checkout predates the hook, restore it with:

```bash
npm run hooks:install
```

## Running Tests

```bash
Expand All @@ -43,27 +67,27 @@ To run tests in watch mode (re-runs on file changes):
npm run test:watch
```

Tests live in `__tests__/` and use Jest with `jest-environment-jsdom`.
Tests live in `__tests__/` and use Vitest with jsdom.

## Linting

```bash
npm run lint
```

Please ensure there are no new lint errors before opening a PR. Lint warnings for `@typescript-eslint/no-explicit-any` are acceptable in the short term but should be addressed progressively.
Please ensure there are no new lint errors before opening a PR.

## Building

```bash
npm run build
```

BRIGx uses `next build` with static export (`output: 'export'`). The built output is placed in `out/`. Always verify the build succeeds before submitting a PR.
BRIGX uses Vite. The built output is placed in `out/`. Always verify the build succeeds before submitting a PR.

## Pull Request Process

1. Create a feature branch from `main`:
1. Create a feature branch from `master`:

```bash
git checkout -b feat/my-feature
Expand All @@ -75,7 +99,7 @@ BRIGx uses `next build` with static export (`output: 'export'`). The built outpu

4. Verify the production build succeeds (`npm run build`).

5. Open a pull request against `main` on GitHub. Fill in the PR template with:
5. Open a pull request against `master` on GitHub. Fill in the PR template with:
- A clear description of what changed and why
- Any relevant issue numbers (e.g. `Closes #42`)
- Notes on manual testing performed
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@
"dev": "vite",
"build": "tsc -b && vite build",
"start": "vite preview",
"typecheck": "tsc --noEmit",
"lint": "eslint .",
"quality:runtime": "node scripts/check-runtime.mjs",
"quality:architecture": "bash scripts/check-architecture.sh",
"quality:portability": "node scripts/check-ci-portability.mjs",
"quality:licenses": "node scripts/check-licenses.mjs",
"quality:security": "node scripts/check-security.mjs",
"test": "vitest run",
Expand All @@ -30,7 +33,12 @@
"test:coverage": "vitest run --coverage",
"test:e2e": "playwright test",
"test:e2e:dev": "playwright test --config playwright.dev.config.ts",
"verify": "npm run lint && npm run quality:architecture && npm run quality:licenses && npm run quality:security && npm test && npm run build && npm run test:e2e && npm run test:e2e:dev"
"verify:ci:core": "npm run quality:runtime && npm run typecheck && npm run lint && npm run quality:architecture && npm run quality:portability && npm run quality:licenses && npm run quality:security && npm test && npm run build",
"verify:ci:browser": "npm run test:e2e",
"verify:ci": "npm run verify:ci:core && npm run verify:ci:browser",
"verify": "npm run verify:ci && npm run test:e2e:dev",
"hooks:install": "node scripts/install-git-hooks.mjs",
"prepare": "npm run hooks:install"
},
"dependencies": {
"@genomicx/ui": "0.9.1",
Expand Down
4 changes: 2 additions & 2 deletions scripts/check-architecture.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ while IFS= read -r source_file; do
fi
done < <(find components hooks lib src workers -type f \( -name '*.ts' -o -name '*.tsx' \) -print | sort)

if rg -n "(from[[:space:]]+|import\()[\"'][^\"']*workers/" components hooks lib src; then
if grep -R -n -E "(from[[:space:]]+|import\()[\"'][^\"']*workers/" components hooks lib src; then
echo "Architecture check: UI/domain modules must not import Web Worker entry modules."
failed=1
fi

if rg -n "from[[:space:]]+[\"'][^\"']*renderer[\"']" lib/canvas-renderer.ts; then
if grep -n -E "from[[:space:]]+[\"'][^\"']*renderer[\"']" lib/canvas-renderer.ts; then
echo "Architecture check: canvas rendering must use shared rendering contracts, not SVG renderer internals."
failed=1
fi
Expand Down
24 changes: 24 additions & 0 deletions scripts/check-ci-portability.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* global console, process */
import { delimiter } from 'node:path';
import { execFileSync } from 'node:child_process';

if (process.platform === 'win32') {
console.log('CI portability check skipped on Windows; GitHub CI runs it on Linux.');
process.exit(0);
}

const systemPath = ['/usr/bin', '/bin'];

try {
execFileSync('bash', ['scripts/check-architecture.sh'], {
env: { ...process.env, PATH: systemPath.join(delimiter) },
stdio: 'inherit',
});
} catch (error) {
console.error(
'CI portability check failed. Quality scripts must use commands available on a clean Ubuntu runner.',
);
process.exit(error.status || 1);
}

console.log('CI portability check passed with system commands only.');
14 changes: 14 additions & 0 deletions scripts/check-runtime.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* global console, process */
import { readFileSync } from 'node:fs';

const expectedMajor = Number.parseInt(readFileSync('.nvmrc', 'utf8').trim(), 10);
const actualMajor = Number.parseInt(process.versions.node.split('.')[0], 10);

if (actualMajor !== expectedMajor) {
console.error(
`BRIGX requires Node.js ${expectedMajor}.x, but this shell is using ${process.version}. Run \`nvm use\` and try again.`,
);
process.exit(1);
}

console.log(`Node.js ${process.version} matches the BRIGX CI runtime.`);
14 changes: 14 additions & 0 deletions scripts/install-git-hooks.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* global console, process */
import { execFileSync } from 'node:child_process';

try {
execFileSync('git', ['rev-parse', '--git-dir'], { stdio: 'ignore' });
} catch {
console.log('Git hooks not installed: this checkout is not a Git worktree.');
process.exit(0);
}

execFileSync('git', ['config', '--local', 'core.hooksPath', '.githooks'], {
stdio: 'inherit',
});
console.log('Installed BRIGX Git hooks from .githooks/.');