1 Commits
Author SHA1 Message Date
sneak b5521672c8 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 06:24:24 +00:00
9 changed files with 157 additions and 79 deletions

No files matched your search

+4 -4
View File
@@ -3,10 +3,10 @@
# recurse into a daemon that does not exist in a build step. # recurse into a daemon that does not exist in a build step.
# #
# In every stage, ARG CACHEBUST comes right after the step that installs # In every stage, ARG CACHEBUST comes right after the step that installs
# system packages: script/ passes a new value on every build, which # system packages. script/ passes a new value on every build. That value
# reruns every RUN step after it and keeps that step's layer. node and # reruns every RUN step below the ARG line, and the install step keeps
# yarn come from the distribution, which is trusted, so they need no # its layer. node and yarn come from the distribution, which is trusted,
# version and no hash. # so they need no version and no hash.
# #
# alpine 3.24.3, 2026-11-04 # alpine 3.24.3, 2026-11-04
FROM alpine@sha256:be2656061b536c1883c4034790e21d0a09c5aaaf51968b89368a3c0371ea2c9a AS lint FROM alpine@sha256:be2656061b536c1883c4034790e21d0a09c5aaaf51968b89368a3c0371ea2c9a AS lint
+4
View File
@@ -28,10 +28,14 @@ fmt-check, and commit.
packages stay pinned by hash. These changed: packages stay pinned by hash. These changed:
- `script/bootstrap` no longer uses nvm or corepack, and stops when yarn's - `script/bootstrap` no longer uses nvm or corepack, and stops when yarn's
major version is not 1. major version is not 1.
- `script/bootstrap` installs node, yarn and the node packages only when
`yarn.lock` is in the tree.
- `script/bootstrap`, `script/fmt` and `script/fmt-check` run `yarn` or - `script/bootstrap`, `script/fmt` and `script/fmt-check` run `yarn` or
`yarnpkg`, whichever is present. `yarnpkg`, whichever is present.
- This repository's `Dockerfile` starts from Alpine 3.24. - This repository's `Dockerfile` starts from Alpine 3.24.
- The Python `test` phase example starts from `debian:trixie-slim`. - The Python `test` phase example starts from `debian:trixie-slim`.
- A Python repository's `script/bootstrap` creates its virtual environment
at `$HOME/.pipenv`, so it works on a host and in a `Dockerfile`.
- `PIP_ONLY_BINARY=:all:` stops a package with no wheel, so pip downloads no - `PIP_ONLY_BINARY=:all:` stops a package with no wheel, so pip downloads no
build tools without a hash check. build tools without a hash check.
- 2026-11-04: Rewrote `prompts/REPO_POLICIES.md` sentence by sentence - 2026-11-04: Rewrote `prompts/REPO_POLICIES.md` sentence by sentence
+2 -2
View File
@@ -1,6 +1,6 @@
--- ---
title: Code Styleguide — JavaScript title: Code Styleguide — JavaScript
last_modified: 2026-02-22 last_modified: 2026-11-04
--- ---
1. Use `const` for everything. If you need to reassign, use `let`. Never use 1. Use `const` for everything. If you need to reassign, use `let`. Never use
@@ -8,7 +8,7 @@ last_modified: 2026-02-22
1. Use yarn for package management, avoid using npm. 1. Use yarn for package management, avoid using npm.
1. Use LTS node versions. 1. Install node from the distribution, in whatever version it packages.
1. Use `prettier` for code formatting, with four spaces for indentation. 1. Use `prettier` for code formatting, with four spaces for indentation.
+25 -14
View File
@@ -81,15 +81,19 @@ with your task.
- pipenv and its dependencies - pipenv and its dependencies
- the packages from `Pipfile.lock` - the packages from `Pipfile.lock`
It installs pipenv and its dependencies by hash, with It creates a virtual environment at `$HOME/.pipenv` with `python3 -m venv`
when it is missing, then uses that environment's `pip` and `pipenv`. On a
host, it first installs the distribution's python and venv packages when
they are missing. It installs pipenv and its dependencies by hash, with
`pip install --require-hashes`. It installs the packages from `Pipfile.lock` `pip install --require-hashes`. It installs the packages from `Pipfile.lock`
with `pipenv install --deploy`, plus `--dev` when the tests need the with `pipenv install --deploy`, plus `--dev` when the tests need the
development packages. It sets `PIP_ONLY_BINARY=:all:` for both installs, so 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 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 Python there, because the tests use the distribution's, which a step above
it installs. The tests run after `ARG CACHEBUST`, and every other stage it installs. `Pipfile` names no `python_version`, because `--deploy` stops
installs its Python packages after it, as in the Python `test` phase example when the distribution's Python differs from it. The tests run after
in `REPO_POLICIES.md` `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 - [ ] The gate phases invoke their tools directly, never through `make lint` or
`script/test` — those are themselves a `docker build` and would recurse `script/test` — those are themselves a `docker build` and would recurse
@@ -198,11 +202,17 @@ with your task.
`docker build` in `script/`. Without the bootstrap the CI run dies in `docker build` in `script/`. Without the bootstrap the CI run dies in
`script/fmt-check`, which runs the formatter on the host and finds nothing `script/fmt-check`, which runs the formatter on the host and finds nothing
installed. installed.
- [ ] `script/bootstrap` installs node and yarn from the distribution when they - [ ] `script/bootstrap` installs node, yarn and the node packages only when
are missing, and stops with a one-line message when yarn's major version `yarn.lock` is in the tree. node and yarn come from the distribution when
is not 1. they are missing. With `yarn.lock` in the tree, `script/bootstrap` stops
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.
- [ ] `script/bootstrap`, `script/fmt` and `script/fmt-check` run yarn by - [ ] `script/bootstrap`, `script/fmt` and `script/fmt-check` run yarn by
whichever name is present: `yarn`, or `yarnpkg` on Debian and Ubuntu. whichever name is present: `yarn`, or `yarnpkg` on Debian and Ubuntu. With
neither name on `PATH`, they print one line saying to run
`script/bootstrap`, and exit 1.
- [ ] `script/bootstrap` installs no linter of its own — delete the block, its - [ ] `script/bootstrap` installs no linter of its own — delete the block, its
version variables and its call site. A JS repo's `yarn install` stays; it version variables and its call site. A JS repo's `yarn install` stays; it
brings a linter along with every other dependency, and no verdict is taken brings a linter along with every other dependency, and no verdict is taken
@@ -264,12 +274,13 @@ with your task.
# Final # Final
- [ ] `make check` passes - [ ] `make check` passes
- [ ] `script/cibuild` succeeds in a fresh clone on a host carrying what CI has - [ ] `script/cibuild` succeeds in a fresh clone on a host carrying what CI has.
(the runner image `docker.gitea.com/runner-images:ubuntu-latest`: docker, That host is the runner image
git and node 24), with any yarn first taken off `PATH`, and demonstrably `docker.gitea.com/runner-images:ubuntu-latest`, which has docker, git and
executed the checks — a sub-second build, or `CACHED` on a step that lints node 24. Take any yarn off `PATH` first. The run must show that the checks
or tests, one of the `RUN` steps below `ARG CACHEBUST`, means nothing ran. executed. A sub-second build means nothing ran. So does `CACHED` on a step
Above that line, these steps are expected to show `CACHED`: that lints or tests, one of the `RUN` steps below `ARG CACHEBUST`. Above
that line, these steps are expected to show `CACHED`:
- the steps that install system packages - the steps that install system packages
- the steps that download Go's modules - the steps that download Go's modules
- the step that runs `script/bootstrap` to install a Python `test` phase's - the step that runs `script/bootstrap` to install a Python `test` phase's
+37 -21
View File
@@ -148,13 +148,18 @@ Template files can be fetched from:
- pipenv and its dependencies - pipenv and its dependencies
- the packages from `Pipfile.lock` - the packages from `Pipfile.lock`
It installs pipenv and its dependencies by hash, with It creates a virtual environment at `$HOME/.pipenv` with
`pip install --require-hashes`. It installs the packages from `python3 -m venv` when it is missing, then uses that environment's `pip`
`Pipfile.lock` with `pipenv install --deploy`, plus `--dev` when the and `pipenv`. On a host, it first installs the distribution's python and
tests need the development packages. It sets `PIP_ONLY_BINARY=:all:` for venv packages when they are missing. It installs pipenv and its
both installs, so a package with no wheel for the image stops the dependencies by hash, with `pip install --require-hashes`. It installs
install. It installs no Python there, because the tests use the the packages from `Pipfile.lock` with `pipenv install --deploy`, plus
distribution's, which a step above it installs. The tests run after `--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 `ARG CACHEBUST`, and every other stage installs its Python packages
after it, as in the Python `test` phase example in `REPO_POLICIES.md` after it, as in the Python `test` phase example in `REPO_POLICIES.md`
@@ -185,13 +190,21 @@ are thin shims calling them. Model scripts:
- [ ] scripts are POSIX sh (`#!/bin/sh`, `set -eu`, no bashisms) so they run on - [ ] scripts are POSIX sh (`#!/bin/sh`, `set -eu`, no bashisms) so they run on
alpine images without bash alpine images without bash
- [ ] `script/bootstrap` / `make bootstrap` — installs all dependencies, - [ ] `script/bootstrap` / `make bootstrap` installs all dependencies,
idempotently, assuming nothing (pkg manager detection nix/apt/brew/apk; idempotently, and assumes nothing is present:
node and yarn from that package manager when they are missing; a one-line - It detects the package manager: nix, apt, brew or apk.
message and a stop when yarn's major version is not 1); a non-server - It installs node, yarn and the node packages only when `yarn.lock` is in
repo's development environment stage runs it, with only system packages the tree. node and yarn come from that package manager when they are
installed inline above it; a gate phase or the build stage installs what missing.
its base image lacks either inline or by running it - With `yarn.lock` in the tree, it stops with a one-line message when yarn's
major version is not 1.
- A non-server repo's development environment stage runs it, with only
system packages installed inline above it.
- A gate phase or the build stage installs what its base image lacks, either
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.
- [ ] `script/setup` / `make setup` — readies a fresh clone: runs `bootstrap`, - [ ] `script/setup` / `make setup` — readies a fresh clone: runs `bootstrap`,
then `install-precommit`, plus repo-specific init then `install-precommit`, plus repo-specific init
- [ ] `script/test` / `make test` — - [ ] `script/test` / `make test` —
@@ -222,7 +235,9 @@ are thin shims calling them. Model scripts:
The bootstrap is required: CI checks out and runs this alone, and The bootstrap is required: CI checks out and runs this alone, and
`script/fmt-check` runs the formatter on the host. `script/fmt-check` runs the formatter on the host.
- [ ] `script/bootstrap`, `script/fmt` and `script/fmt-check` run yarn by - [ ] `script/bootstrap`, `script/fmt` and `script/fmt-check` run yarn by
whichever name is present: `yarn`, or `yarnpkg` on Debian and Ubuntu. whichever name is present: `yarn`, or `yarnpkg` on Debian and Ubuntu. With
neither name on `PATH`, they print one line saying to run
`script/bootstrap`, and exit 1.
- [ ] No `docker build` in `script/` leaves a dangling image behind: - [ ] No `docker build` in `script/` leaves a dangling image behind:
`script/lint` and `script/test` write no image, and `script/docker` and `script/lint` and `script/test` write no image, and `script/docker` and
`script/cibuild` tag theirs `script/cibuild` tag theirs
@@ -237,12 +252,13 @@ are thin shims calling them. Model scripts:
- [ ] `make check` passes - [ ] `make check` passes
- [ ] `make docker` succeeds - [ ] `make docker` succeeds
- [ ] `script/cibuild` succeeds in a fresh clone on a host carrying what CI has - [ ] `script/cibuild` succeeds in a fresh clone on a host carrying what CI has.
(the runner image `docker.gitea.com/runner-images:ubuntu-latest`: docker, That host is the runner image
git and node 24), with any yarn first taken off `PATH`, and demonstrably `docker.gitea.com/runner-images:ubuntu-latest`, which has docker, git and
executed the checks — a sub-second build, or `CACHED` on a step that lints node 24. Take any yarn off `PATH` first. The run must show that the checks
or tests, one of the `RUN` steps below `ARG CACHEBUST`, means nothing ran. executed. A sub-second build means nothing ran. So does `CACHED` on a step
Above that line, these steps are expected to show `CACHED`: that lints or tests, one of the `RUN` steps below `ARG CACHEBUST`. Above
that line, these steps are expected to show `CACHED`:
- the steps that install system packages - the steps that install system packages
- the steps that download Go's modules - the steps that download Go's modules
- the step that runs `script/bootstrap` to install a Python `test` phase's - the step that runs `script/bootstrap` to install a Python `test` phase's
+53 -21
View File
@@ -121,15 +121,27 @@ style conventions are in separate documents:
only when it is missing. A tool from outside the distribution is never only when it is missing. A tool from outside the distribution is never
installed as "latest" or "lts"; it is always an exact version. installed as "latest" or "lts"; it is always an exact version.
`script/bootstrap` installs node, yarn and the node packages only when
`yarn.lock` is in the tree. With no `yarn.lock`, it installs no node and no
yarn, and it does not check yarn's version.
Debian and Ubuntu name the yarn command `yarnpkg`. `script/bootstrap`, Debian and Ubuntu name the yarn command `yarnpkg`. `script/bootstrap`,
`script/fmt` and `script/fmt-check` each carry the same small function that `script/fmt` and `script/fmt-check` each carry the same small function that
runs whichever name is present. runs whichever name is present. With neither name on `PATH`, the function
prints one line saying to run `script/bootstrap`, and exits 1.
`script/bootstrap` stops with a one-line message when yarn's major version With `yarn.lock` in the tree, `script/bootstrap` stops with a one-line
is not 1, before it installs any node packages. Debian 13 and Ubuntu 26.04 message when yarn's major version is not 1, before it installs any node
package yarn 4. With `--frozen-lockfile`, yarn 4 refuses a yarn 1 packages. Debian 13 and Ubuntu 26.04 package yarn 4. With
`yarn.lock`. Without that flag, it rewrites the file and drops the hashes. `--frozen-lockfile`, yarn 4 refuses a yarn 1 `yarn.lock`. Without that flag,
Alpine and Ubuntu 24.04 package yarn 1, so use one of those. 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.
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.
`script/cibuild` runs the CI build, and the Gitea workflow calls it. The `script/cibuild` runs the CI build, and the Gitea workflow calls it. The
script changes to the repo root, runs `script/bootstrap`, runs script changes to the repo root, runs `script/bootstrap`, runs
@@ -189,8 +201,8 @@ style conventions are in separate documents:
running `script/bootstrap`. Only system packages may be installed inline running `script/bootstrap`. Only system packages may be installed inline
above it, so that check builds keep them; the `prompts` repo's own above it, so that check builds keep them; the `prompts` repo's own
`Dockerfile` does this. A stage that runs `script/bootstrap` COPYs `script/` `Dockerfile` does this. A stage that runs `script/bootstrap` COPYs `script/`
and the dependency manifests (`package.json` + `yarn.lock`, `go.mod` + and the dependency manifests it needs (`package.json` + `yarn.lock`,
`go.sum`, etc.) before running it. `go.mod` + `go.sum`, etc.) before running it.
- **Linting and testing run in Docker, as phases of the `Dockerfile`.** There is - **Linting and testing run in Docker, as phases of the `Dockerfile`.** There is
no separate lint file. `script/lint` and `script/test` each build one phase no separate lint file. `script/lint` and `script/test` each build one phase
@@ -507,6 +519,14 @@ style conventions are in separate documents:
distribution's Python, which a step above it installs. If it installs distribution's Python, which a step above it installs. If it installs
anything else there, the step goes after `ARG CACHEBUST`. anything else there, the step goes after `ARG CACHEBUST`.
- Debian's Python refuses a system-wide `pip install`, so pipenv goes in a
virtual environment at `$HOME/.pipenv`. `script/bootstrap` creates it with
`python3 -m venv` when it is missing, then uses that environment's `pip`
and `pipenv`. On a host, it first installs the distribution's python and
venv packages when they are missing. One script then works on a host and
in a `Dockerfile`. `Pipfile` names no `python_version`, because
`pipenv install --deploy` stops when the distribution's Python differs
from it.
- PyPI is not trusted, so `script/bootstrap` installs pipenv and its - PyPI is not trusted, so `script/bootstrap` installs pipenv and its
dependencies by hash. It does so with `pip install --require-hashes -r` dependencies by hash. It does so with `pip install --require-hashes -r`
and a requirements file in `script/` that lists each of them with `==` and and a requirements file in `script/` that lists each of them with `==` and
@@ -532,11 +552,25 @@ style conventions are in separate documents:
A cache mount is shared by every build on the host, and nothing checks its A cache mount is shared by every build on the host, and nothing checks its
files again. files again.
In the example below, `script/bootstrap` does all of these: A Python repository's `script/bootstrap` adds these lines. The `ensurepip`
- finds `make` and `git` already installed test fails when python is missing, and also when Debian's venv package is
- sets `PIP_ONLY_BINARY=:all:` missing:
- installs pipenv and its dependencies by hash
- runs `pipenv install --dev --deploy` ```sh
if [ ! -x "$HOME/.pipenv/bin/pip" ]; then
if ! python3 -m ensurepip --version >/dev/null 2>&1; then
pkg_install python3 python3-venv python3 python3
fi
python3 -m venv "$HOME/.pipenv"
fi
export PIP_ONLY_BINARY=:all:
"$HOME/.pipenv/bin/pip" install --require-hashes -r script/requirements.txt
"$HOME/.pipenv/bin/pipenv" install --dev --deploy
```
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.
```dockerfile ```dockerfile
# Test phase. Both pytest runs share one 90-second timeout, so a hang # Test phase. Both pytest runs share one 90-second timeout, so a hang
@@ -551,11 +585,9 @@ style conventions are in separate documents:
&& apt-get install -y --no-install-recommends ca-certificates make git \ && apt-get install -y --no-install-recommends ca-certificates make git \
python3 python3-pip python3-venv \ python3 python3-pip python3-venv \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# Debian's Python refuses a system-wide pip install, so pipenv goes in a # script/bootstrap installs pipenv in a virtual environment at
# virtual environment. pipenv is not bundled with Python, so # $HOME/.pipenv, and the tests below run that pipenv.
# script/bootstrap installs it by hash, with the pip this puts on PATH. ENV PATH=/root/.pipenv/bin:$PATH
RUN python3 -m venv /opt/pipenv
ENV PATH=/opt/pipenv/bin:$PATH
WORKDIR /app WORKDIR /app
COPY script/ script/ COPY script/ script/
COPY Pipfile Pipfile.lock ./ COPY Pipfile Pipfile.lock ./
@@ -690,16 +722,16 @@ style conventions are in separate documents:
```makefile ```makefile
test: test:
@timeout 90 sh -c 'python -m pytest || { \ @timeout 90 sh -c 'pipenv run pytest || { \
echo "--- Rerunning with -v for details ---"; \ echo "--- Rerunning with -v for details ---"; \
python -m pytest -v; exit 1; }' pipenv run pytest -v; exit 1; }'
``` ```
Both pytest runs share that one 90-second timeout, as in the `Dockerfile` Both pytest runs share that one 90-second timeout, as in the `Dockerfile`
example above, so a hang uses it once and gets no rerun. Ctrl-C does not example above, so a hang uses it once and gets no rerun. Ctrl-C does not
stop a running `make test`, which goes on until the tests end or the 90 stop a running `make test`, which goes on until the tests end or the 90
seconds run out. On a Mac without `timeout`, the target fails until it is seconds run out. On a Mac without `timeout`, the target fails until it is
installed. installed. On a host, the target needs `$HOME/.pipenv/bin` on `PATH`.
The `exit 1` ensures the target always fails after a rerun. The first run The `exit 1` ensures the target always fails after a rerun. The first run
already proved the tests are broken, so the build must not pass even if a already proved the tests are broken, so the build must not pass even if a
+24 -15
View File
@@ -3,7 +3,9 @@
# this repo. Idempotent: every install is guarded by a check so already # this repo. Idempotent: every install is guarded by a check so already
# installed tools are skipped. Base tools, node and yarn come from nix, # installed tools are skipped. Base tools, node and yarn come from nix,
# apt, brew, or apk (detected in that order), with no version and no # apt, brew, or apk (detected in that order), with no version and no
# hash, because the distribution is trusted. Assumes nothing is present. # hash, because the distribution is trusted. It installs node, yarn and
# the node packages only when yarn.lock is in the tree. Assumes nothing
# is present.
set -eu set -eu
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
@@ -60,8 +62,11 @@ missing() {
run_yarn() { run_yarn() {
if command -v yarn >/dev/null 2>&1; then if command -v yarn >/dev/null 2>&1; then
yarn "$@" yarn "$@"
else elif command -v yarnpkg >/dev/null 2>&1; then
yarnpkg "$@" yarnpkg "$@"
else
echo "no yarn; run script/bootstrap first" >&2
exit 1
fi fi
} }
@@ -70,21 +75,25 @@ main() {
if missing make; then pkg_install gnumake make make make; fi if missing make; then pkg_install gnumake make make make; fi
if missing git; then pkg_install git git git git; fi if missing git; then pkg_install git git git git; fi
if missing node; then pkg_install nodejs nodejs node nodejs; fi
if missing yarn && missing yarnpkg; then
pkg_install yarn yarnpkg yarn yarn
fi
# Debian 13 and Ubuntu 26.04 package yarn 4, which refuses a yarn 1 # A Dockerfile stage that needs no yarn copies no yarn.lock.
# yarn.lock, or rewrites it and drops its hashes. if [ -f yarn.lock ]; then
yarn_version="$(run_yarn --version)" if missing node; then pkg_install nodejs nodejs node nodejs; fi
if [ "${yarn_version%%.*}" != "1" ]; then if missing yarn && missing yarnpkg; then
echo "bootstrap: yarn $yarn_version refuses this yarn 1 yarn.lock;" \ pkg_install yarn yarnpkg yarn yarn
"use a distribution that packages yarn 1" >&2 fi
exit 1
fi
run_yarn install --frozen-lockfile # Debian 13 and Ubuntu 26.04 package yarn 4, which refuses a yarn 1
# yarn.lock, or rewrites it in its own format.
yarn_version="$(run_yarn --version)"
if [ "${yarn_version%%.*}" != "1" ]; then
echo "bootstrap: yarn $yarn_version refuses this yarn 1 yarn.lock;" \
"use a distribution that packages yarn 1" >&2
exit 1
fi
run_yarn install --frozen-lockfile
fi
echo "bootstrap complete" echo "bootstrap complete"
} }
+4 -1
View File
@@ -8,8 +8,11 @@ ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
run_yarn() { run_yarn() {
if command -v yarn >/dev/null 2>&1; then if command -v yarn >/dev/null 2>&1; then
yarn "$@" yarn "$@"
else elif command -v yarnpkg >/dev/null 2>&1; then
yarnpkg "$@" yarnpkg "$@"
else
echo "no yarn; run script/bootstrap first" >&2
exit 1
fi fi
} }
+4 -1
View File
@@ -8,8 +8,11 @@ ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
run_yarn() { run_yarn() {
if command -v yarn >/dev/null 2>&1; then if command -v yarn >/dev/null 2>&1; then
yarn "$@" yarn "$@"
else elif command -v yarnpkg >/dev/null 2>&1; then
yarnpkg "$@" yarnpkg "$@"
else
echo "no yarn; run script/bootstrap first" >&2
exit 1
fi fi
} }