Lint static/js/ with ESLint in Docker (closes #120) #486

Merged
clawbot merged 1 commits from issue-120-eslint into next 2026-10-03 04:24:11 +02:00
Collaborator

Nothing linted static/js/, so the JavaScript styleguide REPO_POLICIES.md links to went unchecked. ESLint now lints it in a new js-lint stage of the Dockerfile, on the digest-pinned node 24 LTS image and the yarn that image carries. js-lint starts from a js-deps stage that installs ESLint and stays cached until package.json or yarn.lock changes, so only the lint step re-runs. package.json pins ESLint's version and yarn.lock pins every package's hash. script/lint builds js-lint after the Go lint, and the build stage depends on it, so make check and the image build both fail on a violation.

eslint.config.mjs turns on the two styleguide rules a linter can check, no-var and prefer-const. ESLint's recommended set stays off. The extracted Alpine.js is ignored. static/js/app.js already complied, so it is unchanged.

ESLint prints nothing on a pass, so script/lint cannot require a summary line the way it does for golangci-lint. Instead it names the stage once for both --target and --no-cache-filter. --target fails on a name that matches no stage, so a renamed stage cannot replay a cached pass.

  • Deviation from the plan on #120: no check of the linter's own output, for the reason above.
  • Not covered: the styleguide's prettier rule, which is a formatter's job, not a linter's; prettier is #215.
  • Tried: a var put back into static/js/app.js turned make check red; a let that is never reassigned failed the image build.

Model: opus-5-5

Nothing linted `static/js/`, so the JavaScript styleguide `REPO_POLICIES.md` links to went unchecked. ESLint now lints it in a new `js-lint` stage of the `Dockerfile`, on the digest-pinned node 24 LTS image and the yarn that image carries. `js-lint` starts from a `js-deps` stage that installs ESLint and stays cached until `package.json` or `yarn.lock` changes, so only the lint step re-runs. `package.json` pins ESLint's version and `yarn.lock` pins every package's hash. `script/lint` builds `js-lint` after the Go lint, and the build stage depends on it, so `make check` and the image build both fail on a violation. `eslint.config.mjs` turns on the two styleguide rules a linter can check, `no-var` and `prefer-const`. ESLint's recommended set stays off. The extracted Alpine.js is ignored. `static/js/app.js` already complied, so it is unchanged. ESLint prints nothing on a pass, so `script/lint` cannot require a summary line the way it does for golangci-lint. Instead it names the stage once for both `--target` and `--no-cache-filter`. `--target` fails on a name that matches no stage, so a renamed stage cannot replay a cached pass. - Deviation from the plan on https://git.eeqj.de/sneak/webhooker/issues/120: no check of the linter's own output, for the reason above. - Not covered: the styleguide's prettier rule, which is a formatter's job, not a linter's; prettier is https://git.eeqj.de/sneak/webhooker/issues/215. - Tried: a `var` put back into `static/js/app.js` turned `make check` red; a `let` that is never reassigned failed the image build. Model: opus-5-5
clawbot added the needs-review label 2026-10-03 02:56:17 +02:00
clawbot self-assigned this 2026-10-03 02:56:17 +02:00
Author
Collaborator

Review of #486 for #120: needs rework.

  1. Dockerfile (js-lint stage) and script/lint: --no-cache-filter=js-lint re-runs yarn install along with ESLint. That means every make lint, every make check and every commit through the pre-commit hook downloads ESLint and its dependencies again, and fails when the package registry cannot be reached. The Go linter already avoids this: Dockerfile.lint keeps its module download in a deps stage that stays cached and forces only the stage that lints. REPO_POLICIES.md also asks that the dependency install layer stay cached until the manifests change. Acceptable: install ESLint in its own stage (node image, package.json and yarn.lock, yarn install) and start js-lint from that stage, with COPY . . and the ESLint step. script/lint keeps naming only js-lint. Update the script/lint comment (drop "yarn install included") and the Linting section of README.md to match.

  2. README.md, Prerequisites: "The same holds for ESLint, node and yarn" carries over "must not be installed on the host" from the golangci-lint sentence. That is not true of node and yarn: nothing in the repo breaks or changes when they are installed on the host, and REPO_POLICIES.md has script/bootstrap use a host node when one is present. Acceptable: say that ESLint, node and yarn are not prerequisites and that make lint never uses a host copy.

  • Judgement call: the disclosed deviation (no check of ESLint's own output) is accepted. The reason given holds.
  • Judgement call: the image build now also downloads from the package registry. This is accepted, since REPO_POLICIES.md has the image build run every check.
  • Judgement call: the styleguide's yarn run test/yarn run build item is read as covering JavaScript projects, not a manifest that only pins ESLint.

Model: opus-5-5

Review of https://git.eeqj.de/sneak/webhooker/pulls/486 for https://git.eeqj.de/sneak/webhooker/issues/120: needs rework. 1. `Dockerfile` (`js-lint` stage) and `script/lint`: `--no-cache-filter=js-lint` re-runs `yarn install` along with ESLint. That means every `make lint`, every `make check` and every commit through the pre-commit hook downloads ESLint and its dependencies again, and fails when the package registry cannot be reached. The Go linter already avoids this: `Dockerfile.lint` keeps its module download in a `deps` stage that stays cached and forces only the stage that lints. `REPO_POLICIES.md` also asks that the dependency install layer stay cached until the manifests change. Acceptable: install ESLint in its own stage (node image, `package.json` and `yarn.lock`, `yarn install`) and start `js-lint` from that stage, with `COPY . .` and the ESLint step. `script/lint` keeps naming only `js-lint`. Update the `script/lint` comment (drop "yarn install included") and the Linting section of `README.md` to match. 2. `README.md`, Prerequisites: "The same holds for ESLint, node and yarn" carries over "must not be installed on the host" from the golangci-lint sentence. That is not true of node and yarn: nothing in the repo breaks or changes when they are installed on the host, and `REPO_POLICIES.md` has `script/bootstrap` use a host node when one is present. Acceptable: say that ESLint, node and yarn are not prerequisites and that `make lint` never uses a host copy. - Judgement call: the disclosed deviation (no check of ESLint's own output) is accepted. The reason given holds. - Judgement call: the image build now also downloads from the package registry. This is accepted, since `REPO_POLICIES.md` has the image build run every check. - Judgement call: the styleguide's `yarn run test`/`yarn run build` item is read as covering JavaScript projects, not a manifest that only pins ESLint. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-03 03:40:17 +02:00
clawbot force-pushed issue-120-eslint from 62f8d8578e to 4a514b9cce 2026-10-03 03:56:08 +02:00 Compare
clawbot added needs-review and removed needs-rework labels 2026-10-03 03:56:22 +02:00
Author
Collaborator

Rework of #486:

  1. ESLint is now installed in a new js-deps stage, and js-lint starts from it with only COPY . . and the ESLint step; script/lint still names only js-lint, and its comment and the README's Linting section say the install stays cached.
  2. Prerequisites now says ESLint, node and yarn are not prerequisites and make lint never uses a host copy of them.

A second make lint reused the install and still ran ESLint: a var in static/js/app.js turned it red.

  • Judgement call: dropped the PR body's line saying every make lint downloads ESLint again, since it is no longer true, and named js-deps there.

Model: opus-5-5

Rework of https://git.eeqj.de/sneak/webhooker/pulls/486: 1. ESLint is now installed in a new `js-deps` stage, and `js-lint` starts from it with only `COPY . .` and the ESLint step; `script/lint` still names only `js-lint`, and its comment and the README's Linting section say the install stays cached. 2. Prerequisites now says ESLint, node and yarn are not prerequisites and `make lint` never uses a host copy of them. A second `make lint` reused the install and still ran ESLint: a `var` in `static/js/app.js` turned it red. - Judgement call: dropped the PR body's line saying every `make lint` downloads ESLint again, since it is no longer true, and named `js-deps` there. Model: opus-5-5
Author
Collaborator

Re-review of #486 for #120: needs rework.

  1. .dockerignore and README.md (Docker section, item 3): the rework moved the ESLint install into the new js-deps stage, but these two places still say one stage installs ESLint and runs it. .dockerignore says "The js-lint stage installs ESLint itself". Item 3 calls it the "JavaScript lint stage" that "installs ESLint from yarn.lock and runs it", and item 4 names that stage js-lint. Neither is true of the tree: js-deps installs ESLint, and js-lint only copies the source and runs ESLint. Acceptable: .dockerignore says js-deps installs ESLint and a host copy would overwrite it at js-lint's COPY . .. Item 3 becomes "JavaScript lint stages" and says js-deps installs ESLint from yarn.lock and js-lint runs it over static/js/.
  • Judgement call: both sentences were true before the install moved to js-deps, so they count as introduced by this rework.

Model: opus-5-5

Re-review of https://git.eeqj.de/sneak/webhooker/pulls/486 for https://git.eeqj.de/sneak/webhooker/issues/120: needs rework. 1. `.dockerignore` and `README.md` (Docker section, item 3): the rework moved the ESLint install into the new `js-deps` stage, but these two places still say one stage installs ESLint and runs it. `.dockerignore` says "The js-lint stage installs ESLint itself". Item 3 calls it the "JavaScript lint stage" that "installs ESLint from `yarn.lock` and runs it", and item 4 names that stage `js-lint`. Neither is true of the tree: `js-deps` installs ESLint, and `js-lint` only copies the source and runs ESLint. Acceptable: `.dockerignore` says `js-deps` installs ESLint and a host copy would overwrite it at `js-lint`'s `COPY . .`. Item 3 becomes "JavaScript lint stages" and says `js-deps` installs ESLint from `yarn.lock` and `js-lint` runs it over `static/js/`. - Judgement call: both sentences were true before the install moved to `js-deps`, so they count as introduced by this rework. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-03 04:11:20 +02:00
clawbot added 1 commit 2026-10-03 04:14:13 +02:00
Lint static/js/ with ESLint in Docker (closes #120)
check / check (push) Successful in 3m29s
e82b1cc3df
ESLint, pinned by package.json and yarn.lock, runs in a new js-lint
stage of the Dockerfile on the pinned node 24 LTS image. It starts from
a js-deps stage that installs ESLint and stays cached until those two
files change. script/lint builds js-lint after the Go lint, and the
build stage depends on it, so make check and the image build both fail
on a violation. eslint.config.mjs turns on the styleguide's checkable
rules: no-var and prefer-const.

Model: opus-5-5
clawbot force-pushed issue-120-eslint from 4a514b9cce to e82b1cc3df 2026-10-03 04:14:13 +02:00 Compare
Author
Collaborator

Rework of #486:

  1. .dockerignore now says the js-deps stage installs ESLint and a host copy would overwrite it at the js-lint stage's COPY . .. Item 3 of the README's Docker section is now "JavaScript lint stages": js-deps installs ESLint from yarn.lock and js-lint runs it over static/js/. Item 4 already names js-lint as the stage the builder depends on, so it is unchanged.

The other sentences in the PR that name a stage already match the tree and are unchanged. Rebased onto current next.

  • Judgement call: the directory listing's package.json / yarn.lock line ("ESLint, pinned, for the JavaScript lint stage") is left as is, since js-lint is the stage that runs ESLint.

Model: opus-5-5

Rework of https://git.eeqj.de/sneak/webhooker/pulls/486: 1. `.dockerignore` now says the `js-deps` stage installs ESLint and a host copy would overwrite it at the `js-lint` stage's `COPY . .`. Item 3 of the README's Docker section is now "JavaScript lint stages": `js-deps` installs ESLint from `yarn.lock` and `js-lint` runs it over `static/js/`. Item 4 already names `js-lint` as the stage the builder depends on, so it is unchanged. The other sentences in the PR that name a stage already match the tree and are unchanged. Rebased onto current `next`. - Judgement call: the directory listing's `package.json / yarn.lock` line ("ESLint, pinned, for the JavaScript lint stage") is left as is, since `js-lint` is the stage that runs ESLint. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-10-03 04:14:25 +02:00
Author
Collaborator

Re-review of #486 for #120: passed.

Model: opus-5-5

Re-review of https://git.eeqj.de/sneak/webhooker/pulls/486 for https://git.eeqj.de/sneak/webhooker/issues/120: passed. Model: opus-5-5
clawbot merged commit 74a96b2226 into next 2026-10-03 04:24:11 +02:00
clawbot deleted branch issue-120-eslint 2026-10-03 04:24:11 +02:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/webhooker#486