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
55 changes: 49 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ jobs:

# Install all tarballs together — npm resolves workspace deps from this set
cd "$SMOKE_DIR"
npm init -y
npm install --no-save "$PACKS_DIR"/*.tgz

# Persist the bin dir across steps via GITHUB_PATH
Expand Down Expand Up @@ -100,11 +101,48 @@ jobs:
mkdir -p "$INIT_DIR"
ngcompass init --cwd "$INIT_DIR"
# Confirm a config file was created
ls "$INIT_DIR"/.ngcompassrc* "$INIT_DIR"/ngcompass.config.* 2>/dev/null \
|| ls "$INIT_DIR"/*.ngcompass* 2>/dev/null \
|| (echo "ERROR: no config file created by ngcompass init" && exit 1)
shopt -s nullglob
config_files=(
"$INIT_DIR"/.ngcompassrc*
"$INIT_DIR"/ngcompass.config.*
"$INIT_DIR"/*.ngcompass*
)
if [ "${#config_files[@]}" -eq 0 ]; then
echo "ERROR: no config file created by ngcompass init"
exit 1
fi
printf '%s\n' "${config_files[@]}"
echo "OK: config file created"

- name: Verify analyze output formats
shell: bash
run: |
ANALYZE_DIR="$RUNNER_TEMP/ngcompass-analyze-test"
mkdir -p "$ANALYZE_DIR/src"
ngcompass init --cwd "$ANALYZE_DIR"

cat > "$ANALYZE_DIR/src/app.component.ts" <<'TS'
import { ChangeDetectionStrategy, Component } from '@angular/core';

@Component({
selector: 'app-root',
template: '<h1>Hello</h1>',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {}
TS

cd "$ANALYZE_DIR"
ngcompass analyze --format json --force > report.json
node -e "JSON.parse(require('node:fs').readFileSync('report.json', 'utf8'))"

ngcompass analyze --format sarif --force > report.sarif
node -e "const r = JSON.parse(require('node:fs').readFileSync('report.sarif', 'utf8')); if (r.version !== '2.1.0') process.exit(1)"

ngcompass analyze --format html --force --output report.html
test -s report.html || (echo "ERROR: html report was not written" && exit 1)
echo "OK: analyze output formats verified"

- name: Verify exit codes
shell: bash
run: |
Expand All @@ -113,14 +151,19 @@ jobs:
[ $? -eq 0 ] || (echo "ERROR: --version exited non-zero" && exit 1)

# Unknown command must exit non-zero
ngcompass __unknown_command__ 2>/dev/null || true
CODE=$?
[ $CODE -ne 0 ] || (echo "ERROR: unknown command exited 0" && exit 1)
if ngcompass __unknown_command__ 2>/dev/null; then
echo "ERROR: unknown command exited 0"
exit 1
fi
echo "OK: exit codes correct"

- name: Publish dry-run (catch file leakage before release)
env:
NODE_ENV: production
shell: bash
run: |
pnpm exec turbo build:prod

for pkg in packages/ast packages/cache packages/cli packages/common packages/config \
packages/engine packages/planner packages/reporters packages/rules packages/scanner; do
echo "=== $pkg ==="
Expand Down
75 changes: 45 additions & 30 deletions BETA_TEST_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

**Date:** 2026-04-26
**Branch:** `pre_release_v1_beta`
**Version under test:** 0.0.1 (pre-beta)
**Version under test:** 0.1.0-beta
**Checklist status:** 33 done / 72 remaining (105 total).

---

Expand Down Expand Up @@ -103,8 +104,8 @@ Behavior:

`.github/workflows/ci.yml`:
- **Triggers:** push to `main`/`develop`; PRs.
- **Matrix:** Node 18 / 20 / 22 on **`ubuntu-latest` only**.
- **Steps:** checkout → pnpm install (frozen) → `turbo typecheck test build` (concurrency 4) → coverage gate on Node 20 only → `pnpm audit --prod` → upload to Codecov on Node 20.
- **Matrix:** Node 20.19.x / 22.x on `ubuntu-latest`, `windows-latest`, and `macos-latest`.
- **Steps:** checkout → pnpm install (frozen) → `turbo typecheck test build` (concurrency 4) → packed tarball install smoke → CLI command/output smoke checks → production build + publish dry-run → coverage gate on Node 20.19.x / Ubuntu only → `pnpm audit --prod` → upload to Codecov on Node 20.19.x / Ubuntu.

### 1.8 Build & distribution

Expand Down Expand Up @@ -141,11 +142,12 @@ Caching: memory LRU + disk `cacache`; per-task and per-run global cache.

CI today is Linux-only; the developer machine is Windows.

- [ ] Add `windows-latest` and `macos-latest` to the CI matrix.
- [x] Add `windows-latest` and `macos-latest` to the CI matrix.
- [ ] Path handling on Windows (backslashes vs forward slashes) — scanner, cache, config discovery, `outputPath`.
- [ ] Cache directory creation across OSes.
- [ ] Worker thread spawn — confirm `packages/rules/dist/execution-worker.js` resolves after a packed install on every OS.
- [ ] ANSI color rendering: Windows Terminal, `cmd.exe`, PowerShell, CI logs; verify `NO_COLOR` / `FORCE_COLOR` honored.
- [x] ANSI color rendering: CI logs; verify `NO_COLOR` honored.
- [ ] ANSI color rendering: Windows Terminal, `cmd.exe`, PowerShell; verify `FORCE_COLOR` honored.

**Execution matrix**

Expand All @@ -158,51 +160,59 @@ CI today is Linux-only; the developer machine is Windows.

**Minimum smoke script per OS**

- [ ] `ngcompass --version`
- [ ] `ngcompass --help`
- [ ] `ngcompass init` in a fresh temp dir
- [ ] `ngcompass analyze --format json`
- [x] `ngcompass --version`
- [x] `ngcompass --help`
- [x] `ngcompass init` in a fresh temp dir
- [x] `ngcompass analyze --format json`
- [x] `ngcompass analyze --format sarif`
- [x] `ngcompass analyze --format html --output report.html`
- [ ] `ngcompass analyze --format ui --output report.html`
- [ ] `ngcompass cache info`
- [x] `ngcompass cache info`
- [ ] `ngcompass cache path`

**Windows-specific checks**

- [ ] Project path contains spaces, e.g. `C:\Temp\ng beta app\`
- [ ] Config uses relative `outputPath` and `cache.location`
- [ ] Report path uses backslashes and mixed separators
- [ ] `NO_COLOR=1` disables ANSI escapes in console output
- [x] `NO_COLOR=1` disables ANSI escapes in console output
- [ ] Ctrl+C restores cursor and exits cleanly

**Pass criteria**

- [ ] No OS-specific stack traces
- [ ] Same command returns the same exit code on all supported OSes
- [ ] Packed CLI can resolve worker entry and write reports on all OSes
- [x] Same command returns the same exit code on all supported OSes
- [x] Packed CLI can resolve worker entry and write reports on all CI OSes
- [ ] Generated report and cache artifacts land in the expected directories on all OSes

### 2.2 Distribution / install validation

Local `pnpm test` does not exercise the published shape.

- [ ] `pnpm pack` each package; install tarballs into a fresh project; run `ngcompass --version` and `ngcompass --help`.
- [ ] Install with **npm**, **pnpm**, **yarn classic**, **yarn berry**.
- [x] `pnpm pack` each package; install tarballs into a fresh project; run `ngcompass --version` and `ngcompass --help`.
- [x] Install packed tarballs with **npm**.
- [ ] Install with **pnpm**, **yarn classic**, **yarn berry**.
- [ ] Global install (`npm i -g`) and `npx ngcompass`.
- [ ] Resolve correctly from consumer projects with `"type": "module"` and without (ESM + CJS).
- [ ] `dist/` matches `package.json#files` / `exports`; no `src/` leakage.
- [ ] Shebang preserved on `dist/cli.js` after pack.
- [ ] `npm audit --omit=dev` clean of high/critical advisories.
- [x] `dist/` matches `package.json#files` / `exports`; no `src/` leakage.
- [x] Shebang preserved on `dist/cli.js` after pack.
- [x] `npm audit --omit=dev` clean of high/critical advisories in CI.

### 2.3 Command-surface functional matrix

- [ ] `analyze` — happy path, plus every flag combination listed in §1.2.
- [ ] `init` — fresh dir; existing-config dir without `--force` must refuse; `--cwd` to a remote directory.
- [x] `init` — fresh dir.
- [ ] `init` — existing-config dir without `--force` must refuse; `--cwd` to a remote directory.
- [ ] `config health` — valid, broken, missing config.
- [ ] `cache clear` per `--type`; verify on-disk state after.
- [ ] `cache info` — empty cache, populated cache, corrupted entry.
- [ ] `rules` (list) and `rules <name>` (detail) for each `--preset`.
- [ ] **Exit codes:** 0 success; non-zero on `failOnSeverity` / `maxWarnings` breach; distinct code for fatal vs. analysis-found-issues.
- [ ] Unknown command / unknown flag → helpful error, no stack trace.
- [x] `cache info` — empty cache.
- [ ] `cache info` — populated cache, corrupted entry.
- [x] `rules` (list).
- [ ] `rules <name>` (detail) for each `--preset`.
- [x] **Exit codes:** 0 success; non-zero on `failOnSeverity` / `maxWarnings` breach.
- [ ] **Exit codes:** distinct code for fatal vs. analysis-found-issues.
- [x] Unknown command → non-zero exit.
- [ ] Unknown flag → helpful error, no stack trace.

### 2.4 Real Angular project dogfooding

Expand Down Expand Up @@ -249,9 +259,12 @@ Synthetic fixtures alone are not enough.
### 2.8 Output formats

- [ ] **JSON** — pin and publish a JSON schema; validate output against it; document forwards-compat policy.
- [x] **HTML** — generated by installed CLI and covered by reporter regression tests.
- [ ] **HTML** — open in Chrome / Firefox / Safari; CSS isolated when embedded; 10k-finding report renders without freezing the browser.
- [x] **SARIF** — generated by installed CLI and parsed as SARIF 2.1.0 JSON.
- [ ] **SARIF** — validate against the official 2.1.0 schema (consumed by GitHub code scanning).
- [ ] **Console / text** — snapshot test plus visual review; check `--compact` and color-disable env vars.
- [x] `--output` to: normal writable path.
- [ ] `--output` to: existing path (overwrite policy?), missing parent dir, read-only file.

### 2.9 Error message quality
Expand All @@ -271,18 +284,20 @@ Synthetic fixtures alone are not enough.

### 2.11 Documentation parity

- [x] README documents primary commands, output formats, and beta usage examples.
- [ ] README documents every command, flag, and config key — diff `--help` against README.
- [ ] `CHANGELOG.md` exists, starts at chosen beta version.
- [ ] `LICENSE` present (MIT) and matches `package.json`.
- [ ] Each package's `package.json` has `description`, `repository`, `homepage`, `bugs` populated.
- [ ] Public types: `.d.ts` present in `dist/`; exported types match documented surface.
- [ ] Beta-stability note: warn that config shape may change before 1.0.
- [x] `CHANGELOG.md` exists, starts at chosen beta version.
- [x] `LICENSE` present (MIT) and matches `package.json`.
- [x] Each package's `package.json` has `description`, `repository`, `homepage`, `bugs` populated.
- [x] Public types: `.d.ts` present in `dist/`.
- [ ] Exported types match documented surface.
- [x] Beta-stability note: warn that config shape may change before 1.0.

### 2.12 Telemetry, privacy, security

- [ ] Re-confirm zero outbound network calls (run with `--network=none` in Docker).
- [ ] No developer file paths leaked into shipped artifacts (sourcemaps, embedded errors).
- [ ] `npm publish --dry-run` per package; inspect file list for `tests/`, `.env`, `node_modules`.
- [x] No developer file paths leaked into shipped artifacts via sourcemaps in production package dry-run.
- [x] `npm publish --dry-run` per package; inspect file list for `tests/`, `.env`, `node_modules`.
- [ ] Worker entry path not user-controlled.

### 2.13 Beta release logistics
Expand Down
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Changelog

All notable changes to this project will be documented in this file.

## 0.0.1-beta.0 - Unreleased

### Added

- SARIF output for CI code scanning integrations.
- Branded HTML reports with issue, warning, and parse-error iconography.
- HTML reporter regression coverage for branding, escaping, parse errors, and clean scans.
- CI smoke checks for packaged CLI commands, colorless output, initialization, and exit codes.

### Changed

- Release dry-run now builds through the production release path before validating packaged files.
- Documented runtime support now matches package engine requirements.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 ngcompass

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
44 changes: 40 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Angular static analysis tool for architecture, performance, SSR, and code qualit
- Deep AST analysis of Angular components, templates, and services
- Pluggable rule system with built-in presets (recommended, strict, performance, reactivity)
- Incremental analysis with smart caching
- Multiple output formats: console, JSON, HTML
- Multiple output formats: console, JSON, SARIF, HTML
- Fast execution powered by SWC and OXC parsers

## Installation
Expand Down Expand Up @@ -57,9 +57,9 @@ ngcompass config health
|---|---|
| `-p, --profile <name>` | Select a configuration profile from `profiles` in `ngcompass.config.*` |
| `--force` | Force re-execution, ignoring cache |
| `--format <fmt>` | Output format: `console` (default), `json`, `ui` |
| `--format <fmt>` | Output format: `console` (default), `json`, `sarif`, `html`, `ui` |
| `--compact` | ESLint-style compact output |
| `--output <path>` | Write the `ui` HTML report to a file |
| `--output <path>` | Write the `html` / `ui` report to a file |
| `--rule <id>` | Run a single rule in isolation |

## Configuration
Expand All @@ -76,6 +76,42 @@ export default defineConfig({
});
```

## Output Examples

Write machine-readable JSON for automation:

```bash
ngcompass analyze --format json > ngcompass-results.json
```

Write SARIF for GitHub Code Scanning or other SARIF consumers:

```bash
ngcompass analyze --format sarif > ngcompass.sarif
```

Write a branded HTML report:

```bash
ngcompass analyze --format html --output ngcompass-report.html
```

Use ngcompass in CI and fail on violations:

```bash
ngcompass analyze --format console --compact
```

The CLI exits with `0` when analysis completes without errors and exits non-zero when errors are found or the command cannot run successfully.

## Known Limitations

- Beta releases may change rule names, rule messages, and report layout before `1.0`.
- Angular support should be validated against your project before enforcing ngcompass as a required CI gate.
- Template parsing and static analysis are best-effort; dynamic template construction and highly indirect patterns may not be fully understood.
- SARIF output is intended for code scanning ingestion and may not include every visual detail from the HTML report.
- HTML reports are static files and do not currently include live filtering backed by a server.

## Packages

This is a monorepo. Published packages:
Expand All @@ -95,7 +131,7 @@ This is a monorepo. Published packages:

## Requirements

- Node.js >= 18
- Node.js ^20.19.0 or >=22.12.0
- pnpm >= 8

## License
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ngcompass",
"version": "0.0.1",
"version": "0.1.0-beta",
"private": true,
"description": "Angular static analysis tool for architecture, performance, SSR, and code quality",
"repository": {
Expand All @@ -15,7 +15,7 @@
"packageManager": "pnpm@10.33.0",
"scripts": {
"build": "turbo build",
"build:prod": "NODE_ENV=production turbo build:prod",
"build:prod": "turbo build:prod",
"build:benchmark": "BENCHMARK=true pnpm run build",
"build:profile": "turbo build --profile=profile.json && echo 'Profile saved to profile.json'",
"build:trace": "turbo build --trace",
Expand Down
21 changes: 21 additions & 0 deletions packages/ast/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 ngcompass

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Loading
Loading