1 Commits
Author SHA1 Message Date
sneak fbba979a86 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, installs node and yarn from the
package manager, and stops 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 and sets PIP_ONLY_BINARY=:all:, so pip downloads no
build tools without a hash check.

Model: opus-5-5
2026-11-04 04:57:32 +00:00
9 changed files with 80 additions and 158 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. That value # system packages: script/ passes a new value on every build, which
# reruns every RUN step below the ARG line, and the install step keeps # reruns every RUN step after it and keeps that step's layer. node and
# its layer. node and yarn come from the distribution, which is trusted, # yarn come from the distribution, which is trusted, so they need no
# so they need no version and no hash. # 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,14 +28,10 @@ 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-11-04 last_modified: 2026-02-22
--- ---
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-11-04
1. Use yarn for package management, avoid using npm. 1. Use yarn for package management, avoid using npm.
1. Install node from the distribution, in whatever version it packages. 1. Use LTS node versions.
1. Use `prettier` for code formatting, with four spaces for indentation. 1. Use `prettier` for code formatting, with four spaces for indentation.
+14 -25
View File
@@ -81,19 +81,15 @@ with your task.
- pipenv and its dependencies - pipenv and its dependencies
- the packages from `Pipfile.lock` - the packages from `Pipfile.lock`
It creates a virtual environment at `$HOME/.pipenv` with `python3 -m venv` It installs pipenv and its dependencies by hash, with
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. `Pipfile` names no `python_version`, because `--deploy` stops it installs. The tests run after `ARG CACHEBUST`, and every other stage
when the distribution's Python differs from it. The tests run after installs its Python packages after it, as in the Python `test` phase example
`ARG CACHEBUST`, and every other stage installs its Python packages after in `REPO_POLICIES.md`
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
@@ -202,17 +198,11 @@ 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, yarn and the node packages only when - [ ] `script/bootstrap` installs node and yarn from the distribution when they
`yarn.lock` is in the tree. node and yarn come from the distribution when are missing, and stops with a one-line message when yarn's major version
they are missing. With `yarn.lock` in the tree, `script/bootstrap` stops is not 1.
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. With whichever name is present: `yarn`, or `yarnpkg` on Debian and Ubuntu.
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
@@ -274,13 +264,12 @@ 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
That host is the runner image (the runner image `docker.gitea.com/runner-images:ubuntu-latest`: docker,
`docker.gitea.com/runner-images:ubuntu-latest`, which has docker, git and git and node 24), with any yarn first taken off `PATH`, and demonstrably
node 24. Take any yarn off `PATH` first. The run must show that the checks executed the checks — a sub-second build, or `CACHED` on a step that lints
executed. A sub-second build means nothing ran. So does `CACHED` on a step or tests, one of the `RUN` steps below `ARG CACHEBUST`, means nothing ran.
that lints or tests, one of the `RUN` steps below `ARG CACHEBUST`. Above Above that line, these steps are expected to show `CACHED`:
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
+21 -37
View File
@@ -148,18 +148,13 @@ 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 creates a virtual environment at `$HOME/.pipenv` with It installs pipenv and its dependencies by hash, with
`python3 -m venv` when it is missing, then uses that environment's `pip` `pip install --require-hashes`. It installs the packages from
and `pipenv`. On a host, it first installs the distribution's python and `Pipfile.lock` with `pipenv install --deploy`, plus `--dev` when the
venv packages when they are missing. It installs pipenv and its tests need the development packages. It sets `PIP_ONLY_BINARY=:all:` for
dependencies by hash, with `pip install --require-hashes`. It installs both installs, so a package with no wheel for the image stops the
the packages from `Pipfile.lock` with `pipenv install --deploy`, plus install. It installs no Python there, because the tests use the
`--dev` when the tests need the development packages. It sets distribution's, which a step above it installs. The tests run after
`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`
@@ -190,21 +185,13 @@ 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, and assumes nothing is present: idempotently, assuming nothing (pkg manager detection nix/apt/brew/apk;
- It detects the package manager: nix, apt, brew or apk. node and yarn from that package manager when they are missing; a one-line
- It installs node, yarn and the node packages only when `yarn.lock` is in message and a stop when yarn's major version is not 1); a non-server
the tree. node and yarn come from that package manager when they are repo's development environment stage runs it, with only system packages
missing. installed inline above it; a gate phase or the build stage installs what
- With `yarn.lock` in the tree, it stops with a one-line message when yarn's its base image lacks either inline or by running it
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` —
@@ -235,9 +222,7 @@ 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. With whichever name is present: `yarn`, or `yarnpkg` on Debian and Ubuntu.
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
@@ -252,13 +237,12 @@ 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
That host is the runner image (the runner image `docker.gitea.com/runner-images:ubuntu-latest`: docker,
`docker.gitea.com/runner-images:ubuntu-latest`, which has docker, git and git and node 24), with any yarn first taken off `PATH`, and demonstrably
node 24. Take any yarn off `PATH` first. The run must show that the checks executed the checks — a sub-second build, or `CACHED` on a step that lints
executed. A sub-second build means nothing ran. So does `CACHED` on a step or tests, one of the `RUN` steps below `ARG CACHEBUST`, means nothing ran.
that lints or tests, one of the `RUN` steps below `ARG CACHEBUST`. Above Above that line, these steps are expected to show `CACHED`:
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
+21 -53
View File
@@ -121,27 +121,15 @@ 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. With neither name on `PATH`, the function runs whichever name is present.
prints one line saying to run `script/bootstrap`, and exits 1.
With `yarn.lock` in the tree, `script/bootstrap` stops with a one-line `script/bootstrap` stops with a one-line message when yarn's major version
message when yarn's major version is not 1, before it installs any node is not 1, before it installs any node packages. Debian 13 and Ubuntu 26.04
packages. Debian 13 and Ubuntu 26.04 package yarn 4. With package yarn 4. With `--frozen-lockfile`, yarn 4 refuses a yarn 1
`--frozen-lockfile`, yarn 4 refuses a yarn 1 `yarn.lock`. Without that flag, `yarn.lock`. Without that flag, it rewrites the file and drops the hashes.
it rewrites the file in its own format, with its own hashes in place of Alpine and Ubuntu 24.04 package yarn 1, so use one of those.
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
@@ -201,8 +189,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 it needs (`package.json` + `yarn.lock`, and the dependency manifests (`package.json` + `yarn.lock`, `go.mod` +
`go.mod` + `go.sum`, etc.) before running it. `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
@@ -519,14 +507,6 @@ 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
@@ -552,25 +532,11 @@ 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.
A Python repository's `script/bootstrap` adds these lines. The `ensurepip` In the example below, `script/bootstrap` does all of these:
test fails when python is missing, and also when Debian's venv package is - finds `make` and `git` already installed
missing: - sets `PIP_ONLY_BINARY=:all:`
- installs pipenv and its dependencies by hash
```sh - runs `pipenv install --dev --deploy`
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
@@ -585,9 +551,11 @@ 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/*
# script/bootstrap installs pipenv in a virtual environment at # Debian's Python refuses a system-wide pip install, so pipenv goes in a
# $HOME/.pipenv, and the tests below run that pipenv. # virtual environment. pipenv is not bundled with Python, so
ENV PATH=/root/.pipenv/bin:$PATH # script/bootstrap installs it by hash, with the pip this puts on 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 ./
@@ -722,16 +690,16 @@ style conventions are in separate documents:
```makefile ```makefile
test: test:
@timeout 90 sh -c 'pipenv run pytest || { \ @timeout 90 sh -c 'python -m pytest || { \
echo "--- Rerunning with -v for details ---"; \ echo "--- Rerunning with -v for details ---"; \
pipenv run pytest -v; exit 1; }' python -m 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. On a host, the target needs `$HOME/.pipenv/bin` on `PATH`. installed.
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
+16 -25
View File
@@ -3,9 +3,7 @@
# 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. It installs node, yarn and # hash, because the distribution is trusted. Assumes nothing is present.
# 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)"
@@ -62,11 +60,8 @@ 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 "$@"
elif command -v yarnpkg >/dev/null 2>&1; then
yarnpkg "$@"
else else
echo "no yarn; run script/bootstrap first" >&2 yarnpkg "$@"
exit 1
fi fi
} }
@@ -75,26 +70,22 @@ 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
# A Dockerfile stage that needs no yarn copies no yarn.lock. if missing yarn && missing yarnpkg; then
if [ -f yarn.lock ]; then pkg_install yarn yarnpkg yarn yarn
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
# 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 fi
# Debian 13 and Ubuntu 26.04 package yarn 4, which refuses a yarn 1
# yarn.lock, or rewrites it and drops its hashes.
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
echo "bootstrap complete" echo "bootstrap complete"
} }
+1 -4
View File
@@ -8,11 +8,8 @@ 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 "$@"
elif command -v yarnpkg >/dev/null 2>&1; then
yarnpkg "$@"
else else
echo "no yarn; run script/bootstrap first" >&2 yarnpkg "$@"
exit 1
fi fi
} }
+1 -4
View File
@@ -8,11 +8,8 @@ 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 "$@"
elif command -v yarnpkg >/dev/null 2>&1; then
yarnpkg "$@"
else else
echo "no yarn; run script/bootstrap first" >&2 yarnpkg "$@"
exit 1
fi fi
} }