UNPKG

snyk-docker-plugin

Version:
160 lines (123 loc) 7.37 kB
# AGENTS.md Guidance for AI coding agents (Claude Code, Cursor, Copilot, etc.) working in this repo. ## What this is `snyk-docker-plugin` is a library that extracts dependency metadata from container images. It is consumed as a library — there is no CLI entry point of its own. The public surface is exported from `lib/index.ts` (`scan`, `display`, `extractContent`, `dockerFile`, plus the supporting types). Known consumers include: - `snyk/cli` — scan handler - `snyk/kubernetes-monitor` — scan handler - `snyk/container-image-collector` — scan handler (with `--exclude-app-vulns`) - `snyk/docker-registry-agent` — scan handler - `snyk/docker-deps` — types, Dockerfile/image analysis - `snyk/kubernetes-upstream`, `snyk/kubernetes-agent`, `snyk/registry` — types only Treat any change to `PluginResponse`, `ScanResult`, `Fact`, or `FactType` (and the dockerfile-analysis types) as a public-API change with multiple downstream consumers, not just the CLI. ## Output model: `PluginResponse` and Facts `scan()` returns a `PluginResponse` containing one or more `ScanResult`s. Each `ScanResult` carries a list of typed `Fact` objects — this is the contract with every downstream consumer (see "What this is" above). All `FactType` values are enumerated in `lib/types.ts`; concrete shapes live in `lib/facts.ts`. Common ones: - `depGraph` — a `@snyk/dep-graph` for a package manager or application - `dockerfileAnalysis` — base image, instructions, layers - `imageLayers`, `imageId`, `imageNames`, `imageOsReleasePrettyName`, `imageSizeBytes`, `imageCreationTime`, `imageLabels` - `jarFingerprints`, `keyBinariesHashes` — for things not installed by a package manager - `imageManifestFiles` — raw manifest contents (e.g. `requirements.txt`) - `pluginVersion`, `pluginWarnings` When adding a new ecosystem or signal, emit a `Fact` with an existing `FactType` if one fits; introducing a new `FactType` is a contract change affecting every consumer and should be flagged in the PR. ## Repo layout ``` lib/ scan.ts Top-level entry: scan(options) -> PluginResponse index.ts Public exports extractor/ Read images: docker-archive, oci-archive, kaniko-archive analyzer/ Identify OS, package managers, applications, runtimes inputs/ Per-ecosystem file readers (apk, apt, rpm, node, java, python, php, binaries, ...) parser/ Parse package manager databases into dep graphs dependency-tree/ Dep graph construction helpers dockerfile/ Dockerfile parsing and base-image analysis go-parser/ Go binary parsing python-parser/ Python package parsing test/ unit/ lib/ Fast tests, no Docker required system/ Integration tests; require a running Docker daemon + auth env vars fixtures/ Image archives and sample data ``` ## Setup - Node `>=20.19` (see `.nvmrc`: `20`). - `npm install` against the public npm registry. The `@snyk/*` runtime dependencies are published publicly — no auth needed for local install. (CI writes an `NPM_TOKEN` to `.npmrc`; you don't need to replicate that.) - `npm run build` compiles TypeScript to `dist/`. ## Commands Use these exact scripts — don't invent new ones. | Task | Command | | -------------------- | --------------------------------------------------- | | Build | `npm run build` | | Lint (all) | `npm run lint` | | Auto-format + fix | `npm run format` | | Unit tests (default) | `npm run test:unit` | | System tests | `npm run test:system` (requires Docker — see below) | | All tests | `npm test` | For a quick inner loop, `npm run test:unit` is fastest. Run `npm run test:system` (or full `npm test`) before declaring a change done, provided Docker and the required env vars are available — see below. If they aren't, say so explicitly rather than skipping silently. ## Testing rules - **New tests must be Jest, with the `.spec.ts` suffix.** Files ending in `.test.ts` are legacy `tap` tests — do not add new ones, and prefer migrating rather than extending them. - Jest config: `jest.config.js` (root) and `test/windows/jest.config.js`. - System tests need: - A running Docker daemon (with "Use containerd for pulling and storing images" **disabled** in Docker Desktop — containerd causes SHA mismatches). - Env vars `DOCKER_HUB_PRIVATE_IMAGE`, `DOCKER_HUB_USERNAME`, `DOCKER_HUB_PASSWORD` (values in 1Password). - At runtime, the plugin itself reads `SNYK_REGISTRY_USERNAME` / `SNYK_REGISTRY_PASSWORD` — these are separate from the test creds. - See `test/README.md` for the authoritative details. ### Snapshots Some tests use Jest snapshots (`__snapshots__/` directories). Update with `npx jest -u <pattern>` and **review the diff** — snapshot churn often hides real behavior changes. Note: `jest.config.js` pins a custom `snapshotFormat` to keep pre-Jest-29 snapshots readable; don't change it casually. ## Debugging - The library uses the [`debug`](https://www.npmjs.com/package/debug) package. Set `DEBUG=snyk-docker-plugin*` (or a more specific namespace) when running tests or a consumer to see internal logs. - `npm run debug` runs `tsc-watch` with `node --inspect --inspect-brk` for step-through debugging in an attached debugger. ## CI CircleCI (`.circleci/config.yml`) runs build, lint, and tests on: - Linux (`cimg/node:20.19`) — full Jest suite, including system tests - Windows (`win/server-2022`) — `test/windows/` suite via `npm run test-jest-windows` `main`-branch failures notify Slack `#team-container-pipeline-info`. Match the target Node major (`20`) when validating locally. ## Commit & PR conventions - **Conventional commits, enforced by commitlint** (`@commitlint/config-conventional`). Allowed types: `feat`, `fix`, `docs`, `test`, `chore`, `refactor`, `style`, `perf`. Header max length 100. Example: `fix: handle empty layer in OCI archive`. - For a bug fix, prefer committing a **failing test first**, then the fix in a separate commit (see `.github/CONTRIBUTING.md`). - CODEOWNERS: `@snyk/container_container` reviews everything by default. ## Things not to touch - `dist/` — generated by `tsc`, gitignored, never hand-edit. - Test fixtures under `test/fixtures/` are large and load-bearing — don't regenerate or "tidy" them without a clear reason. ## Style - TypeScript, formatted by Prettier (`{ "trailingComma": "all", "arrowParens": "always" }`) and linted by tslint. Run `npm run format` before sending changes. - Prefer editing existing files in `lib/<area>/` over creating new top-level modules. Mirror the existing per-ecosystem layout (`inputs/<eco>`, `analyzer/applications/<eco>`, `parser/<eco>`). ## When in doubt - Public API: read `lib/index.ts` and `lib/types.ts`. - How a scan flows end-to-end: start at `lib/scan.ts`. - How to add support for a new ecosystem: look at an existing one under `lib/inputs/` + `lib/analyzer/applications/` + `lib/parser/` as a template.