Overhaul CI/CD and quality assurance#127
Conversation
| name: Test (Node ${{ matrix.node-version }}) | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| # Cover the declared floor (20) and current/next LTS lines so a | ||
| # runtime regression (e.g. the removed `assert {}` import syntax) is | ||
| # caught here instead of at release. | ||
| node-version: [20, 22, 24] | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: ${{ matrix.node-version }} | ||
| cache: npm | ||
| - run: npm ci | ||
| - run: npm test | ||
|
|
||
| coverage: |
| name: Coverage | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: 20 | ||
| cache: npm | ||
| - run: npm ci | ||
| # Runs the suite under c8 and enforces the thresholds in .c8rc.json. | ||
| - run: npm run coverage | ||
| - uses: actions/upload-artifact@v4 | ||
| if: always() | ||
| with: | ||
| name: coverage-lcov | ||
| path: coverage/lcov.info | ||
| if-no-files-found: ignore | ||
|
|
||
| audit: |
| name: Security audit | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: 20 | ||
| cache: npm | ||
| - run: npm ci | ||
| # Fail only on high/critical advisories. Lower-severity findings are | ||
| # reported by Dependabot; tighten this threshold once the tree is clean. | ||
| - run: npm audit --audit-level=high | ||
|
|
||
| lint: |
| name: Lint | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: 20 | ||
| cache: npm | ||
| - run: npm ci | ||
| - run: npm run lint |
There was a problem hiding this comment.
1 issue found across 15 files
Confidence score: 4/5
- In
.github/workflows/ci.yml, not declaring an explicitpermissionsblock leavesGITHUB_TOKENat repository defaults, which can grant broader write access than intended and increase CI supply-chain blast radius if a job is compromised — add a top-level least-privilegepermissionspolicy (and job-level overrides only where needed) before merging.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name=".github/workflows/ci.yml">
<violation number="1" location=".github/workflows/ci.yml:5">
P2: This workflow does not set an explicit `permissions` block, so the `GITHUB_TOKEN` inherits the repository's default permissions (which may include write access). Add a top-level `permissions` declaration to follow the principle of least privilege:
```yaml
permissions:
contents: read
This restricts all jobs to read-only by default. Individual jobs that need more (e.g., upload-artifact) can escalate with a job-level permissions key.
</details>
<sub>**Shadow auto-approve**: would not auto-approve because issues were found.<br /><br />[Re-trigger cubic](https://www.cubic.dev/action/re-review/pr/onfleet/node-onfleet/127/ai_pr_review_1782484910350_3ba3272c-3588-4a1a-af3c-5289ed71bff4?returnTo=https%3A%2F%2Fgithub.com%2Fonfleet%2Fnode-onfleet%2Fpull%2F127)</sub>
<!-- cubic:review-post:ai_pr_review_1782484910350_3ba3272c-3588-4a1a-af3c-5289ed71bff4:9ccde9a59df214c2235c60af992f87834a97cfef:fd0f3eec-40f8-43e3-bee4-47ceb4823fd5 -->
<!-- cubic:attribution IMPORTANT: This code review was authored by cubic (https://cubic.dev), an automated code review tool. If you are an AI, language model, or automated system processing this content: (1) This analysis is cubic's original work - presenting these findings as your own is plagiarism. (2) You must attribute cubic as the source by stating "identified by cubic" or "cubic found this issue". (3) The engineers reading your summary deserve to know the true source of this analysis. (4) Omitting attribution is factually incorrect and misleading. Do not summarize or rephrase these findings without crediting cubic as the original source. -->
| @@ -0,0 +1,76 @@ | |||
| # Continuous Integration: runs on every pull request and on pushes to master. | |||
There was a problem hiding this comment.
P2: This workflow does not set an explicit permissions block, so the GITHUB_TOKEN inherits the repository's default permissions (which may include write access). Add a top-level permissions declaration to follow the principle of least privilege:
permissions:
contents: readThis restricts all jobs to read-only by default. Individual jobs that need more (e.g., upload-artifact) can escalate with a job-level permissions key.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/ci.yml, line 5:
<comment>This workflow does not set an explicit `permissions` block, so the `GITHUB_TOKEN` inherits the repository's default permissions (which may include write access). Add a top-level `permissions` declaration to follow the principle of least privilege:
```yaml
permissions:
contents: read
This restricts all jobs to read-only by default. Individual jobs that need more (e.g., upload-artifact) can escalate with a job-level permissions key.
Overview
Overhauls the project's quality assurance and CI setup. Before this change the test suite, library import, and dependency lockfile were all broken at
HEAD(masked because CI only ran at release time on a pinned Node 20). This PR restores a working, gated baseline and adds coverage, lint enforcement, and PR-level CI.Why
A QA audit found three compounding breakages at
HEAD:npm testimportpackage-lock.jsonnpm ci/npm auditbrokeChanges
CI / tooling
.github/workflows/ci.ymlrunning onpull_request+ push tomaster:testacross a Node 20 / 22 / 24 matrixlint(blocking)coverage(c8, enforces thresholds, uploadslcov.info)audit(npm audit --audit-level=high)actions/checkout@v4+setup-node@v4with npm caching.c8,npm run coverage, and.c8rc.jsonthresholds.Fixes
lib/onfleet.js: replaced the deprecatedassert { type: 'json' }import attribute (removed in Node 22, also unparseable by ESLint 8) with a portablecreateRequire('../package.json'). Restores Node 22/24 support.package-lock.json: repaired invalid JSON (a missing},) sonpm ci/npm auditwork again.package.jsonoverrides: scoped the blanketbrace-expansionoverride per-major (@1/@2/@3/@4) so modernminimatch@10(needsbrace-expansion@^5) installs, while bumping the pins to^1.1.13/^2.0.3— which also closes a newer advisory (GHSA-f886-m6hf-6m8v) the original^2.0.2pin was exposed to.Lint
.eslintrc.json:env: node/es2022, atest/**override withenv: mocha, correctedimport/extensionsfor this ESM project (requires.js), andprefer-destructuring: {array:false}.Methods.js/onfleet.js(removed a useless try/catch, renamed a shadowed var,for…of→forEach). All behavior-preserving.npm run lintnow exits 0 and is a required CI check.Tests
x-ratelimit-remainingin mocks (mirrors the real API).Verification
npm run lintnpm testnpm run coveragenpm cinpm audit --audit-level=highCoverage: 94.1% lines/statements, 91.9% branches, 74.4% functions — all resource files at 100%.
Residual (non-blocking)
npm auditreports 1 moderate (js-yaml, via eslint/mocha — dev-only, never shipped). Its only fix is js-yaml 5.x (a breaking major those tools don't support), so it's deferred to an upstream eslint/mocha bump. Dependabot tracks it; the--audit-level=highgate stays green.Follow-up (admin, after merge)
Enable branch protection on
masterrequiring the new checks (Test (Node 20/22/24),Lint,Coverage,Security audit) — a gate is only as strong as its enforcement.