Found while reviewing #219, which had to regenerate static/css/tailwind.css.
Makefile:53 invokes a bare tailwindcss from PATH. There is no package.json, no version pin, and no hash pin anywhere. So the committed generated artefact depends entirely on whichever tailwind binary happens to be installed on the machine that ran make css.
Consequences, in order of how much they bite:
The CSS is a COMMITTED, SERVED artefact. Nothing in Dockerfile or script/ regenerates it, so whatever is in the tree is what users get. A regeneration on a different tailwind version silently changes the shipped stylesheet.
Two contributors running make css can produce different output from identical input, and neither can tell which is correct.
This is what already went wrong: #219 added ten classes to a template and the CSS was not regenerated, so the chevron <svg> rendered at the 300x150 CSS default on every delivery row. The gate could not catch it because nothing verifies the artefact matches the templates.
The tailwind CLI is not present on this host at all, so the regeneration had to be done in an ad-hoc container. It produced correct output, but by a route the repo does not define.
It also sits against the repo policy of hash-pinning external references, which the golangci-lint image digest and the script/bootstrap release-archive sha256 pins already follow.
Definition of done:
tailwindcss is pinned to an exact version, hash-pinned consistent with how the lint image and bootstrap archives are pinned
make css runs it in a container the same way linting does, rather than depending on a host binary
a check fails when static/css/tailwind.css does not match what the pinned tailwind produces from the current templates and input.css — that is the part that would have caught #219's missing classes
regenerating on the pinned version produces no diff against the committed artefact, or the one-time reflow is committed in the same change
Found while reviewing https://git.eeqj.de/sneak/webhooker/pulls/219, which had to regenerate `static/css/tailwind.css`.
`Makefile:53` invokes a bare `tailwindcss` from `PATH`. There is no `package.json`, no version pin, and no hash pin anywhere. So the committed generated artefact depends entirely on whichever tailwind binary happens to be installed on the machine that ran `make css`.
Consequences, in order of how much they bite:
- The CSS is a COMMITTED, SERVED artefact. Nothing in `Dockerfile` or `script/` regenerates it, so whatever is in the tree is what users get. A regeneration on a different tailwind version silently changes the shipped stylesheet.
- Two contributors running `make css` can produce different output from identical input, and neither can tell which is correct.
- This is what already went wrong: https://git.eeqj.de/sneak/webhooker/pulls/219 added ten classes to a template and the CSS was not regenerated, so the chevron `<svg>` rendered at the 300x150 CSS default on every delivery row. The gate could not catch it because nothing verifies the artefact matches the templates.
- The tailwind CLI is not present on this host at all, so the regeneration had to be done in an ad-hoc container. It produced correct output, but by a route the repo does not define.
It also sits against the repo policy of hash-pinning external references, which the `golangci-lint` image digest and the `script/bootstrap` release-archive sha256 pins already follow.
Definition of done:
- `tailwindcss` is pinned to an exact version, hash-pinned consistent with how the lint image and bootstrap archives are pinned
- `make css` runs it in a container the same way linting does, rather than depending on a host binary
- a check fails when `static/css/tailwind.css` does not match what the pinned tailwind produces from the current templates and `input.css` — that is the part that would have caught https://git.eeqj.de/sneak/webhooker/pulls/219's missing classes
- regenerating on the pinned version produces no diff against the committed artefact, or the one-time reflow is committed in the same change
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Found while reviewing #219, which had to regenerate
static/css/tailwind.css.Makefile:53invokes a baretailwindcssfromPATH. There is nopackage.json, no version pin, and no hash pin anywhere. So the committed generated artefact depends entirely on whichever tailwind binary happens to be installed on the machine that ranmake css.Consequences, in order of how much they bite:
Dockerfileorscript/regenerates it, so whatever is in the tree is what users get. A regeneration on a different tailwind version silently changes the shipped stylesheet.make csscan produce different output from identical input, and neither can tell which is correct.<svg>rendered at the 300x150 CSS default on every delivery row. The gate could not catch it because nothing verifies the artefact matches the templates.It also sits against the repo policy of hash-pinning external references, which the
golangci-lintimage digest and thescript/bootstraprelease-archive sha256 pins already follow.Definition of done:
tailwindcssis pinned to an exact version, hash-pinned consistent with how the lint image and bootstrap archives are pinnedmake cssruns it in a container the same way linting does, rather than depending on a host binarystatic/css/tailwind.cssdoes not match what the pinned tailwind produces from the current templates andinput.css— that is the part that would have caught #219's missing classes