Repository navigation
v0.8.0
Two checks on what a pull request brings in and on how its tests ran. Dependency safety, signals D01 to D05
(DEPENDENCY_D01 to DEPENDENCY_D05, the report's dependencies object), checks the npm and Python dependencies a
pull request adds or changes: offline and on by default, D04 flags lockfile drift and D05 a dependency from a git
repository, a URL outside the npm and PyPI registries or a local file; with dependencies: lookup the Action also asks
the registries whether an added package exists (D01), is young (D02) or is rarely downloaded (D03). Flaky tests: the new
junit-paths input (CLI --junit) reads the JUnit XML the test step wrote, fills the report's flaky object and a
🧫 Flaky comment section and applies the org's quarantine list, and the new pharn-ci test command runs a test command
and exits 0 when only quarantined tests failed; test results never change the verdict. A behaviour change: dependency
safety runs by default (dependencies: auto) and D04 and D05 are errors, so a pull request that changes a manifest's
dependencies without its lockfile, or adds a git, URL or local-file dependency, now fails the check where it passed;
set dependencies: never to get the old behaviour back. A Dependabot bump and a lockfile-only refresh give no finding.
The CLI and the Action now read the committed text of the manifests and lockfiles a change touches, and with
dependencies: lookup the Action sends the names of added unscoped packages to registry.npmjs.org, api.npmjs.org and
pypi.org, the first hosts other than GitHub and pharn.dev it calls (Security below). A run upload also carries a
redacted junit/results.xml. Report v2 gains the optional dependencies object, fills the optional flaky object and
adds the new message codes; no field, input or code was removed or renamed.
Added
- Flaky tests (A6): the new
junit-pathsinput (CLI:--junit, repeatable) reads the JUnit XML the test step wrote,
with a hand-written, linear reader that refuses any DOCTYPE and expands no entity, capped at 50 files, 25 MiB and
20,000 test cases. Report v2 fills its optionalflakyobject (counts, and up to 200 quarantined test ids that
failed), the comment gains a 🧫 Flaky section, and four codes are added:JUNIT_NOT_FOUND,JUNIT_INVALID,
JUNIT_TOO_LARGE(warn) andFLAKY_QUARANTINED_FAILURES(info). The app's quarantine list from the policy
response is now applied unless the org policy setsflaky.quarantine: false; test results never change the
verdict. A run upload also carriesjunit/results.xml, rebuilt from the parsed cases with failure messages redacted
and cut to 2 KB (never the file, neversystem-outorsystem-err), unless the org setssettings.uploadJunit: false;sizes.junitis no longer always 0. The newpharn-ci test [--junit <glob>]... [--quarantine-file <path>] [--dry-run] -- <command>runs a test command without a shell and exits 0 when it failed only because of quarantined
tests, otherwise with the command's own code. A test id is<classname>::<name>(README, Flaky tests and JUnit
results). - Dependency safety (A13), signals D01 to D05, for the dependencies a pull request adds or changes in npm manifests and
lockfiles (package.json,package-lock.json,npm-shrinkwrap.json,pnpm-lock.yaml,yarn.lock) and Python
ones (requirements files,pyproject.toml,poetry.lock,uv.lock). Offline and on by default (new input
dependencies, defaultauto; CLI flag--dependencies): D04 lockfile drift (block: a manifest's dependencies
changed while its lockfile did not or does not record them, or a lockfile gives the same version a new hash) and D05
a source outside the npm and PyPI registries (block: git, another host, a local file, or a new package index).
Opt-in withdependencies: lookup(ordependencies.lookup: truein.pharn/ci.yml, or the org policy's new
dependencies.lookupkey inschema/policy.v1.json): the Action looks each added unscoped package up in
registry.npmjs.org,api.npmjs.organdpypi.org, sending only the package name in aGET, for D01 package does
not exist (block), D02 first published fewer thanmin_age_days(30) days before the head commit (warn) and D03
fewer thanmin_weekly_downloads(100) npm downloads last week (warn); lookups fail open to
DEPENDENCY_LOOKUP_UNAVAILABLE(warn)..pharn/ci.ymlmay only tighten (lookup: truenever overrules anever
input; the minimums only rise); an app policy with adependencieskey requires the check. Report v2 gains the
optionaldependenciesobject (checked,lookups,signals,truncated,unread) and the codes
DEPENDENCY_D01toDEPENDENCY_D05,DEPENDENCY_LOOKUP_UNAVAILABLEandDEPENDENCY_CHECK_INCOMPLETE; the PR comment
gains a 📦 Dependencies section. A block finding fails the verdict like an agent config secret. A Dependabot bump
and a lockfile-only refresh give no finding. Limits in docs/LIMITS.md, Dependency safety.
Security
- The CLI and the Action now read the committed text of the manifests and lockfiles a change touches (at most 5 MiB
each) at the merge base and at HEAD, unlessdependencies: never; a finding names a path, a line, fixed words and
only allow-listed package names and version specs (docs/THREAT-MODEL.mdrow C9). Withdependencies: lookupthe
Action sends the names of added unscoped packages toregistry.npmjs.org,api.npmjs.organdpypi.org, the first
requests to hosts other than GitHub and pharn.dev (SECURITY.md, Data handling; row D8, residual 43).