1 Commits
Author SHA1 Message Date
sneak 3dc8b419b8 Install node, yarn and python from the distribution (closes #146)
check / check (push) Canceled after 0s
Follows sneak's ruling at
#146 (comment). Runtimes
and the installer tools bundled with python come from the distribution,
with no version and no hash. Third-party packages stay pinned by hash.

script/bootstrap drops nvm and corepack. It installs node, yarn and the
node packages only when yarn.lock is in the tree, and stops there when
yarn's major version is not 1. This repository's Dockerfile starts from
Alpine 3.24. The Python example starts from debian:trixie-slim, keeps
pipenv at $HOME/.pipenv on a host and in an image, and sets
PIP_ONLY_BINARY=:all:, so pip downloads no build tools without a hash
check.

Model: opus-5-5
2026-11-04 07:26:19 +00:00
4 changed files with 32 additions and 23 deletions
+2 -1
View File
@@ -8,7 +8,8 @@ last_modified: 2026-11-04
1. Use yarn for package management, avoid using npm.
1. Install node from the distribution, in whatever version it packages.
1. Install node from the distribution. If its version is too old, use a newer
distribution.
1. Use `prettier` for code formatting, with four spaces for indentation.
+7 -7
View File
@@ -88,12 +88,12 @@ with your task.
`pip install --require-hashes`. It installs the packages from `Pipfile.lock`
with `pipenv install --deploy`, plus `--dev` when the tests need the
development packages. It sets `PIP_ONLY_BINARY=:all:` for both installs, so
a package with no wheel for the image stops the install. It installs no
Python there, because the tests use the distribution's, which a step above
it installs. `Pipfile` names no `python_version`, because `--deploy` stops
when the distribution's Python differs from it. The tests run after
`ARG CACHEBUST`, and every other stage installs its Python packages after
it, as in the Python `test` phase example in `REPO_POLICIES.md`
a package with no wheel for the image stops the install. In that step it
installs no Python, because a step above it already did. `Pipfile` names no
`python_version`, because `--deploy` stops when the distribution's Python
differs from it. The tests run after `ARG CACHEBUST`, and every other stage
installs its Python packages after it, as in the Python `test` phase example
in `REPO_POLICIES.md`
- [ ] The gate phases invoke their tools directly, never through `make lint` or
`script/test` — those are themselves a `docker build` and would recurse
@@ -208,7 +208,7 @@ with your task.
with a one-line message when yarn's major version is not 1.
- [ ] A `Dockerfile` stage copies `yarn.lock` before it runs `script/bootstrap`
only if that stage needs yarn. A stage that needs yarn starts from an
image whose distribution packages yarn 1, which today means Alpine.
image whose distribution packages yarn 1, such as Alpine.
- [ ] `script/bootstrap`, `script/fmt` and `script/fmt-check` run yarn by
whichever name is present: `yarn`, or `yarnpkg` on Debian and Ubuntu. With
neither name on `PATH`, they print one line saying to run
+7 -7
View File
@@ -156,12 +156,12 @@ Template files can be fetched from:
the packages from `Pipfile.lock` with `pipenv install --deploy`, plus
`--dev` when the tests need the development packages. It sets
`PIP_ONLY_BINARY=:all:` for both installs, so a package with no wheel
for the image stops the install. It installs no Python there, because
the tests use the distribution's, which a step above it installs.
`Pipfile` names no `python_version`, because `--deploy` stops when the
distribution's Python differs from it. The tests run after
`ARG CACHEBUST`, and every other stage installs its Python packages
after it, as in the Python `test` phase example in `REPO_POLICIES.md`
for the image stops the install. In that step it installs no Python,
because a step above it already did. `Pipfile` names no
`python_version`, because `--deploy` stops when the distribution's
Python differs from it. The tests run after `ARG CACHEBUST`, and every
other stage installs its Python packages after it, as in the Python
`test` phase example in `REPO_POLICIES.md`
- Server: the final stage builds and runs the application
- Non-server: the final stage brings up the dev environment
@@ -204,7 +204,7 @@ are thin shims calling them. Model scripts:
inline or by running it.
- [ ] A `Dockerfile` stage copies `yarn.lock` before it runs `script/bootstrap`
only if that stage needs yarn. A stage that needs yarn starts from an
image whose distribution packages yarn 1, which today means Alpine.
image whose distribution packages yarn 1, such as Alpine.
- [ ] `script/setup` / `make setup` — readies a fresh clone: runs `bootstrap`,
then `install-precommit`, plus repo-specific init
- [ ] `script/test` / `make test` —
+16 -8
View File
@@ -135,13 +135,14 @@ style conventions are in separate documents:
packages. Debian 13 and Ubuntu 26.04 package yarn 4. With
`--frozen-lockfile`, yarn 4 refuses a yarn 1 `yarn.lock`. Without that flag,
it rewrites the file in its own format, with its own hashes in place of
these. Alpine and Ubuntu 24.04 package yarn 1, so a host uses one of those.
these. A host whose distribution packages yarn 4 moves to one that packages
yarn 1, such as Alpine or Ubuntu 24.04.
A `Dockerfile` stage copies `yarn.lock` before it runs `script/bootstrap`
only if that stage needs yarn. A stage that needs yarn starts from an image
whose distribution packages yarn 1, which today means Alpine. The Python and
Go stages below need no yarn, so they copy no `yarn.lock` before that step
and never reach the stop.
whose distribution packages yarn 1, such as Alpine. The Python and Go stages
below need no yarn, so they copy no `yarn.lock` before that step and never
reach the stop.
`script/cibuild` runs the CI build, and the Gitea workflow calls it. The
script changes to the repo root, runs `script/bootstrap`, runs
@@ -552,9 +553,9 @@ style conventions are in separate documents:
A cache mount is shared by every build on the host, and nothing checks its
files again.
A Python repository's `script/bootstrap` adds these lines. The `ensurepip`
test fails when python is missing, and also when Debian's venv package is
missing:
A Python repository's `script/bootstrap` adds these lines in `main`, above
the last `echo`. The `ensurepip` test fails when python is missing, and also
when Debian's venv package is missing:
```sh
if [ ! -x "$HOME/.pipenv/bin/pip" ]; then
@@ -568,6 +569,13 @@ style conventions are in separate documents:
"$HOME/.pipenv/bin/pipenv" install --dev --deploy
```
Make `script/requirements.txt` once with
`echo pipenv | pip-compile --generate-hashes --allow-unsafe -o script/requirements.txt -`,
from Alpine's `py3-pip-tools` package, because Debian and Ubuntu do not
package it. Make the first `Pipfile.lock` with
`$HOME/.pipenv/bin/pipenv lock`, after the `pip install` line has installed
pipenv.
In the example below, `script/bootstrap` finds `make`, `git`, python and
venv already installed. The example copies no `yarn.lock`, so
`script/bootstrap` installs no node and no yarn.
@@ -583,7 +591,7 @@ style conventions are in separate documents:
# stay in their own layer when script/ changes.
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates make git \
python3 python3-pip python3-venv \
python3 python3-venv \
&& rm -rf /var/lib/apt/lists/*
# script/bootstrap installs pipenv in a virtual environment at
# $HOME/.pipenv, and the tests below run that pipenv.