Dependabot alerts 12 and 13 name postcss-selector-parser and
source-map-js in the root lock file. Both reach the project through
stylelint. The lock now holds postcss-selector-parser 7.1.6 and
source-map-js 1.2.2, the first releases outside the advisories.
Alert 11 on braces stays open, no fixed release exists.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Merging the stylelint 17.16.0 and the globals 17.13.0 bump dropped the comma after stylelint and left a trailing one after globals, in package.json and package-lock.json alike. Neither file was JSON any more, so npm could not read the lock and npm ci refused with EUSAGE: 'can only install with an existing package-lock.json'. make lint died in install-lint before a single linter ran, which is the whole lint job on every branch that carries main.
The two entries move into the alphabetical order npm writes them in and the commas follow. No version changes: the lock already resolved stylelint 17.16.0 and globals 17.13.0, only the devDependencies block was malformed. npm ci --dry-run now resolves the tree instead of refusing it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Dependabot alert 6 on infinito-nexus/core flags js-yaml 4.3.1 in the
root package-lock.json: maxTotalMergeKeys does not limit CPU use for
empty merge sources, affecting >= 4.0.0, < 4.3.2. It arrives as a
development dependency through stylelint 17.15.0 -> cosmiconfig 9.0.2,
whose ^4.1.0 range already admits the patched release, so only the
js-yaml entry changes.
The resolved URL and integrity are the ones registry.npmjs.org serves
for 4.3.2; npm run inside the dev container had written the package
cache's /repository/npm-proxy/ path into resolved, which does not exist
on the public registry.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adding stylelint left package-lock.json out of sync, and I regenerated it with
`npm install --package-lock-only` inside the compose container. That container
resolves npm through package-cache:8081, so npm rewrote 110 `resolved` URLs to
`registry.npmjs.org/repository/npm-proxy/…` — a path that exists only behind
that proxy. The integrity hashes were never wrong; only the place to fetch from.
It took down two CI jobs from one mistake. The test job probes external URLs
and got 108 HTTP 404s. The lint job never linted at all: install-lint died
fetching write-file-atomic from the same dead path, so every lint target behind
it was skipped rather than run.
A local `make quality-high` cannot catch this class. The sandbox has no route to
the registry, so the reachability check degrades to a warning and the run goes
green on an unanswered question. That is worth remembering beyond this fix:
green here is not evidence for anything that needs the network.
Verified this time: all 184 resolved URLs answer HTTP 200, and a structural
diff against the pre-stylelint lockfile shows 110 packages added, none removed,
and no existing package altered in version or integrity.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Four parse checks join the `lint-*` family, each using the language's own
parser rather than a reimplementation: `php -l`, `ruby -c`, `sqlfluff parse`,
and stylelint with an empty rule set (it raises CssSyntaxError whatever the
rules say, so the check stays syntax-only and grows no style opinion). Three
unit runners join `test-unit`: node:test, PHPUnit, minitest -- the first and
third ship with their runtime, so only PHPUnit adds a dependency.
Provisioning is best effort and the lint script decides whether it can run. A
machine without PHP must not fail the gate, but it must not look like success
either: the skip names how many files went unchecked. The first version of
these scripts read `git ls-files`, which inside the compose container returns
nothing (git refuses the bind-mounted repo as "dubious ownership") and reported
"No SQL files found." over 52 files -- green, and a lie. They use `find` now,
as the surrounding lint scripts already did.
sqlfluff needed two corrections before it parsed anything real. `%(name)s` is a
psycopg parameter marker, not SQL, so the placeholder templater is configured
rather than the files exempted; and the dialect follows each role's declared
engine (`meta/services.yml`), which is postgres for six roles and mysql for
svc-db-mariadb and pixelfed.
Recipes stay in scripts, not in the Makefile: the targets delegate, matching
every other target in the file.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Each role's Playwright spec is staged the same way `test-e2e-playwright` does at deploy time (central config + personas tree + service-gating) and `npx playwright test --list` runs against it. `--list` skips the browser launch and any test body, so this catches refactor regressions like missing helpers, broken exports, or syntax errors in seconds instead of waiting for a full deploy. Stub env values keyed off the variable-name suffix satisfy the few specs that build URLs or call `.replace()` at module-load time.
Parallelism caps at `INFINITO_WORKER_CPU` (same env knob as `scripts/make/parallel.sh`); output is replayed in `SPEC_FILES` order after all workers drain so stdout stays deterministic. `@playwright/test` ships as a devDep via the existing eslint `npm ci`. Workflow wires into `ci-orchestrator.yml` behind the `lint-gate`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wires JavaScript linting into the project for the first time, scoped to
the Playwright specs and persona helpers under `roles/**/files/**/*.js`.
Setup
-----
- `package.json` + `package-lock.json` pin eslint v9, eslint-plugin-
playwright v2, @eslint/js, globals.
- `eslint.config.js` (flat config) loads `eslint:recommended` and
`playwright/flat/recommended`. Browser globals are injected so
`page.evaluate(() => window.foo)` callbacks lint cleanly. Project-
idiomatic patterns are explicitly turned off with rationale: the
service-gating contract (req 006/019) uses test.skip on disabled
services; persona helpers branch on isVisible/isServiceEnabled before
expect; some specs deliberately use waitForTimeout / networkidle for
OIDC settle. `no-empty` allows the empty-catch idiom; the autofixer
for `prefer-web-first-assertions` and `no-wait-for-navigation` is
unsafe in this codebase (broken diff in dashboard.js), so both are
off pending a hand-migration pass.
- `scripts/lint/javascript.sh` mirrors the markdown.sh shape (skip on
missing, exit 127 with "make install-lint" hint).
- `scripts/lint/autoformat.sh` gets a `run_eslint` worker (treats rc≤1
as OK, like markdownlint).
- `scripts/install/lint.sh` gets `ensure_eslint` (npm-local install in
the repo root, matching the markdownlint pattern), a `javascript`
group, and `install_javascript_tools` is wired into the `all` group.
- `Makefile` exposes `lint-javascript` and folds it into the aggregate
`lint` target.
- `.github/workflows/lint-javascript.yml` follows the lint-makefile.yml
shape (Node 20, npm cache, `npm ci`, `make lint-javascript`); the
ci-orchestrator wires it into the lint pipeline + lint-gate `needs:`.
- `.gitignore` adds `node_modules/`.
Real lint findings fixed in this commit
---------------------------------------
- `roles/web-app-decidim/files/playwright.spec.js` was using
`runBiberFlow` / `runAdminFlow` without ever requiring `./personas`
(would have failed at runtime). Adds the require.
- Same file: two nutzlose `\\'csrf-token\\'` escapes in a double-quoted
query selector — eslint flagged, fixed.
- `roles/web-app-moodle/files/playwright.spec.js`:
`expect(await locator.count()).toBe(0)` →
`await expect(locator).toHaveCount(0)` (Playwright auto-retrying
assertion; safe `prefer-to-have-count` autofix).
Lint baseline: 0 errors, 285 warnings (mostly `no-unused-vars` and
`playwright/expect-expect` — addressable as follow-up cleanup, not
blocking).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>