Compare commits
8
Commits
7f4ef15610
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed5ed236b1 | ||
|
|
6c489067ce | ||
|
|
c4d5546e86 | ||
|
|
7b55c444ae | ||
|
|
c3a504f647 | ||
|
|
85bea7681e | ||
|
|
58f75147be | ||
|
|
58eafaf4c2 |
+40
-1
@@ -10,13 +10,20 @@ run:
|
|||||||
|
|
||||||
linters:
|
linters:
|
||||||
default: all
|
default: all
|
||||||
|
enable:
|
||||||
|
# Successor to the deprecated gomodguard. Named explicitly, rather than
|
||||||
|
# left to `default: all`, because it carries the module policy below.
|
||||||
|
- gomodguard_v2
|
||||||
disable:
|
disable:
|
||||||
# Genuinely incompatible with project patterns
|
# Genuinely incompatible with project patterns
|
||||||
- exhaustruct # Requires all struct fields
|
- exhaustruct # Requires all struct fields
|
||||||
- godot # Requires comments to end with periods
|
- godot # Requires comments to end with periods
|
||||||
- wsl # Deprecated, replaced by wsl_v5
|
|
||||||
- wrapcheck # Too verbose for internal packages
|
- wrapcheck # Too verbose for internal packages
|
||||||
- varnamelen # Short names like db, id are idiomatic Go
|
- varnamelen # Short names like db, id are idiomatic Go
|
||||||
|
# Deprecated: the warning is attached to the old name, so it is
|
||||||
|
# silenced by disabling that name, not by enabling the successor.
|
||||||
|
- wsl # Deprecated, replaced by wsl_v5
|
||||||
|
- gomodguard # Deprecated, replaced by gomodguard_v2
|
||||||
settings:
|
settings:
|
||||||
lll:
|
lll:
|
||||||
line-length: 88
|
line-length: 88
|
||||||
@@ -53,6 +60,38 @@ linters:
|
|||||||
desc: >-
|
desc: >-
|
||||||
Test-support code belongs in test files and in packages whose
|
Test-support code belongs in test files and in packages whose
|
||||||
directory name ends in test, not in the shipped binary.
|
directory name ends in test, not in the shipped binary.
|
||||||
|
# Only decisions already recorded in the Go package defaults are
|
||||||
|
# listed here. Every entry matches the module path exactly.
|
||||||
|
gomodguard_v2:
|
||||||
|
blocked:
|
||||||
|
- module: github.com/rs/zerolog
|
||||||
|
recommendations:
|
||||||
|
- log/slog
|
||||||
|
reason: "Structured logging is stdlib log/slog."
|
||||||
|
# One entry per pre-fork module path, because the later releases
|
||||||
|
# are separate paths. A prefix match would be shorter but would
|
||||||
|
# also reach github.com/go-redis/redismock, the test double for
|
||||||
|
# the successor these entries recommend.
|
||||||
|
- module: github.com/go-redis/redis
|
||||||
|
recommendations:
|
||||||
|
- github.com/redis/go-redis/v9
|
||||||
|
reason: "Pre-fork module; use the maintained go-redis v9."
|
||||||
|
- module: github.com/go-redis/redis/v7
|
||||||
|
recommendations:
|
||||||
|
- github.com/redis/go-redis/v9
|
||||||
|
reason: "Pre-fork module; use the maintained go-redis v9."
|
||||||
|
- module: github.com/go-redis/redis/v8
|
||||||
|
recommendations:
|
||||||
|
- github.com/redis/go-redis/v9
|
||||||
|
reason: "Pre-fork module; use the maintained go-redis v9."
|
||||||
|
- module: github.com/sergi/go-diff
|
||||||
|
recommendations:
|
||||||
|
- github.com/aymanbagabas/go-udiff
|
||||||
|
reason: "No unified diff output; use go-udiff."
|
||||||
|
- module: github.com/hexops/gotextdiff
|
||||||
|
recommendations:
|
||||||
|
- github.com/aymanbagabas/go-udiff
|
||||||
|
reason: "Unmaintained fork; use go-udiff."
|
||||||
|
|
||||||
issues:
|
issues:
|
||||||
max-issues-per-linter: 0
|
max-issues-per-linter: 0
|
||||||
|
|||||||
@@ -123,16 +123,17 @@ alpine. We provide:
|
|||||||
- `script/fmt` — format all markdown files with prettier (writes; native, not in
|
- `script/fmt` — format all markdown files with prettier (writes; native, not in
|
||||||
a container)
|
a container)
|
||||||
- `script/fmt-check` — check formatting (read-only; native)
|
- `script/fmt-check` — check formatting (read-only; native)
|
||||||
- `script/check` — run all checks: `test`, `lint`, `fmt-check`, then
|
- `script/check` — run all checks: `test`, `lint`, `fmt-check` (our own
|
||||||
`docker build -t prompts .` (our own extension; no `--no-cache` there, because
|
extension); builds no image of its own
|
||||||
the two phases that build depends on were just built without it)
|
|
||||||
- `script/docker` —
|
- `script/docker` —
|
||||||
`docker build --no-cache --build-arg VERSION="$version" -t prompts .`, the tag
|
`docker build --no-cache --build-arg VERSION="$version" -t prompts .`, the tag
|
||||||
coming from `script/projectname` (byte-identical across repos)
|
coming from `script/projectname` (byte-identical across repos)
|
||||||
- `script/cibuild` — cd to the repo root, compute `version` from `git describe`,
|
- `script/cibuild` — cd to the repo root, run `script/bootstrap`, run
|
||||||
run `script/check`, then
|
`script/check`, compute `version` from `git describe`, then
|
||||||
`docker build --build-arg VERSION="$version" -t prompts .` (what CI runs; the
|
`docker build --no-cache --build-arg VERSION="$version" -t prompts .` (what CI
|
||||||
version is computed on the host because `.dockerignore` excludes `.git`)
|
runs; it bootstraps because CI checks out and runs this alone while
|
||||||
|
`script/fmt-check` is native, and the version is computed on the host because
|
||||||
|
`.dockerignore` excludes `.git`)
|
||||||
- `script/precommit` — run by the git pre-commit hook (our own extension); calls
|
- `script/precommit` — run by the git pre-commit hook (our own extension); calls
|
||||||
`script/check`
|
`script/check`
|
||||||
- `script/install-precommit` — installs the git pre-commit hook (our own
|
- `script/install-precommit` — installs the git pre-commit hook (our own
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ fmt-check, and commit.
|
|||||||
they pass. This also closes issue 30: a container has its own result cache and
|
they pass. This also closes issue 30: a container has its own result cache and
|
||||||
its own lock, so a lint verdict can no longer belong to another checkout. No
|
its own lock, so a lint verdict can no longer belong to another checkout. No
|
||||||
separate lint Dockerfile, and no `golangci-lint config verify` step.
|
separate lint Dockerfile, and no `golangci-lint config verify` step.
|
||||||
|
`script/check` runs the gates and nothing else, and `script/cibuild`
|
||||||
|
bootstraps first, since it is all CI runs and `script/fmt-check` is native.
|
||||||
- 2026-09-08: Kept in-repo agent scratch out of the Docker build context and out
|
- 2026-09-08: Kept in-repo agent scratch out of the Docker build context and out
|
||||||
of version control: `.claude/` is one full checkout of the repo per in-flight
|
of version control: `.claude/` is one full checkout of the repo per in-flight
|
||||||
agent, and under `COPY . .` all of it was reaching the image. Also closed the
|
agent, and under `COPY . .` all of it was reaching the image. Also closed the
|
||||||
@@ -51,6 +53,15 @@ fmt-check, and commit.
|
|||||||
layers cannot be served from cache on an unchanged tree, and the text claiming
|
layers cannot be served from cache on an unchanged tree, and the text claiming
|
||||||
a bare `docker build .` proves the checks ran is corrected in
|
a bare `docker build .` proves the checks ran is corrected in
|
||||||
`REPO_POLICIES.md`, both checklists and the Go styleguide.
|
`REPO_POLICIES.md`, both checklists and the Go styleguide.
|
||||||
|
- 2026-09-03: Added `-count=1` to both `go test` invocations in the canonical Go
|
||||||
|
`make test` example in `REPO_POLICIES.md`, so the target cannot report a
|
||||||
|
cached pass it did not earn, and documented that Go's test-result cache is a
|
||||||
|
second, independent cache stacked below the Docker layer cache.
|
||||||
|
- 2026-08-31: Migrated the canonical `.golangci.yml` from the deprecated
|
||||||
|
`gomodguard` to `gomodguard_v2`: the old linter is disabled by name (which is
|
||||||
|
what silences the deprecation warning), the successor is named explicitly in
|
||||||
|
`linters.enable`, and it carries a `blocked` module list drawn only from
|
||||||
|
decisions already recorded in the Go package defaults.
|
||||||
- 2026-08-07: Set the canonical `.golangci.yml` to the org-standard v2-schema
|
- 2026-08-07: Set the canonical `.golangci.yml` to the org-standard v2-schema
|
||||||
config already deployed byte-identical across the org's Go repos (settings
|
config already deployed byte-identical across the org's Go repos (settings
|
||||||
under `linters.settings` so thresholds like lll/funlen/cyclop/dupl actually
|
under `linters.settings` so thresholds like lll/funlen/cyclop/dupl actually
|
||||||
|
|||||||
@@ -99,6 +99,15 @@ with your task.
|
|||||||
on the host.
|
on the host.
|
||||||
- [ ] Every `docker build` in `script/` is tagged — an untagged one leaves a
|
- [ ] Every `docker build` in `script/` is tagged — an untagged one leaves a
|
||||||
dangling image behind on every run, on every host and CI runner
|
dangling image behind on every run, on every host and CI runner
|
||||||
|
- [ ] `script/cibuild` runs `script/bootstrap` before `script/check`, and builds
|
||||||
|
the image with `--no-cache`. Without the bootstrap the CI run dies in
|
||||||
|
`script/fmt-check`, which runs the formatter on the host and finds nothing
|
||||||
|
installed.
|
||||||
|
- [ ] `script/fmt` and `script/fmt-check` source nvm for the pinned node version
|
||||||
|
before invoking `yarn`, as `script/bootstrap`'s own install step does.
|
||||||
|
`script/bootstrap` leaves the node and yarn it installs off the `PATH` of
|
||||||
|
the shell that called it, so a bare `yarn` exits 127 on a runner carrying
|
||||||
|
nothing but docker and git.
|
||||||
- [ ] `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
|
||||||
@@ -151,8 +160,10 @@ with your task.
|
|||||||
# Final
|
# Final
|
||||||
|
|
||||||
- [ ] `make check` passes
|
- [ ] `make check` passes
|
||||||
- [ ] `script/cibuild` succeeds and demonstrably executed the checks — a
|
- [ ] `script/cibuild` succeeds in a fresh clone on a host carrying nothing but
|
||||||
sub-second build, or `CACHED` on a gate layer, means nothing ran
|
docker and git, with no node or yarn on `PATH`, which is what CI has, and
|
||||||
|
demonstrably executed the checks — a sub-second build, or `CACHED` on a
|
||||||
|
gate layer, means nothing ran
|
||||||
- [ ] A planted lint violation fails both `make lint` and a plain
|
- [ ] A planted lint violation fails both `make lint` and a plain
|
||||||
`docker build .`; revert it afterwards
|
`docker build .`; revert it afterwards
|
||||||
- [ ] Commit and merge fixes before starting your actual task
|
- [ ] Commit and merge fixes before starting your actual task
|
||||||
|
|||||||
@@ -113,15 +113,23 @@ are thin shims calling them. Model scripts:
|
|||||||
container)
|
container)
|
||||||
- [ ] `script/fmt-check` / `make fmt-check` — checks formatting (read-only;
|
- [ ] `script/fmt-check` / `make fmt-check` — checks formatting (read-only;
|
||||||
native)
|
native)
|
||||||
- [ ] `script/check` / `make check` — runs `test`, `lint`, `fmt-check`, then
|
- [ ] `script/check` / `make check` — runs `test`, `lint`, `fmt-check`; must not
|
||||||
builds the image; must not modify files
|
modify files
|
||||||
- [ ] `script/projectname` — outputs the project name (used by `script/docker`
|
- [ ] `script/projectname` — outputs the project name (used by `script/docker`
|
||||||
for the image tag)
|
for the image tag)
|
||||||
- [ ] `script/docker` / `make docker` — builds Docker image, tagged via
|
- [ ] `script/docker` / `make docker` — builds Docker image, tagged via
|
||||||
`script/projectname` (byte-identical across repos); `--no-cache`, plus the
|
`script/projectname` (byte-identical across repos); `--no-cache`, plus the
|
||||||
version as a build arg
|
version as a build arg
|
||||||
- [ ] `script/cibuild` — cd to repo root, run `script/check`, then
|
- [ ] `script/cibuild` — cd to repo root, run `script/bootstrap`, run
|
||||||
`docker build --build-arg VERSION="$version" .` (what CI runs)
|
`script/check`, then
|
||||||
|
`docker build --no-cache --build-arg VERSION="$version" .` (what CI runs).
|
||||||
|
The bootstrap is required: CI checks out and runs this alone, and
|
||||||
|
`script/fmt-check` runs the formatter on the host.
|
||||||
|
- [ ] `script/fmt` and `script/fmt-check` source nvm for the pinned node version
|
||||||
|
before invoking `yarn`, as `script/bootstrap`'s own install step does.
|
||||||
|
`script/bootstrap` leaves the node and yarn it installs off the `PATH` of
|
||||||
|
the shell that called it, so a bare `yarn` exits 127 on a runner carrying
|
||||||
|
nothing but docker and git.
|
||||||
- [ ] Every `docker build` in `script/` is tagged, so no invocation leaves a
|
- [ ] Every `docker build` in `script/` is tagged, so no invocation leaves a
|
||||||
dangling image behind
|
dangling image behind
|
||||||
- [ ] `script/precommit` — called by the pre-commit hook; runs `script/check`
|
- [ ] `script/precommit` — called by the pre-commit hook; runs `script/check`
|
||||||
@@ -135,8 +143,10 @@ are thin shims calling them. Model scripts:
|
|||||||
|
|
||||||
- [ ] `make check` passes
|
- [ ] `make check` passes
|
||||||
- [ ] `make docker` succeeds
|
- [ ] `make docker` succeeds
|
||||||
- [ ] `script/cibuild` succeeds and demonstrably executed the checks — a
|
- [ ] `script/cibuild` succeeds in a fresh clone on a host carrying nothing but
|
||||||
sub-second build, or `CACHED` on a gate layer, means nothing ran
|
docker and git, with no node or yarn on `PATH`, which is what CI has, and
|
||||||
|
demonstrably executed the checks — a sub-second build, or `CACHED` on a
|
||||||
|
gate layer, means nothing ran
|
||||||
- [ ] Plant a lint violation and confirm both `make lint` and a plain
|
- [ ] Plant a lint violation and confirm both `make lint` and a plain
|
||||||
`docker build .` fail on it; revert. A plain build that passes proves the
|
`docker build .` fail on it; revert. A plain build that passes proves the
|
||||||
final stage is missing its `COPY --from=` edge to the gate phases.
|
final stage is missing its `COPY --from=` edge to the gate phases.
|
||||||
|
|||||||
+47
-20
@@ -60,10 +60,20 @@ style conventions are in separate documents:
|
|||||||
prerequisite since nvm requires bash. yarn is then pinned via
|
prerequisite since nvm requires bash. yarn is then pinned via
|
||||||
`corepack prepare yarn@<version> --activate`. Never install "latest" or "lts";
|
`corepack prepare yarn@<version> --activate`. Never install "latest" or "lts";
|
||||||
always exact versions. `script/cibuild` runs the CI build: it changes to the
|
always exact versions. `script/cibuild` runs the CI build: it changes to the
|
||||||
repo root, runs `script/check`, and builds the image with the version; the
|
repo root, runs `script/bootstrap`, runs `script/check`, and builds the image
|
||||||
Gitea workflow calls it. Four further scripts are our own extensions to the
|
with the version; the Gitea workflow calls it. **`script/cibuild` runs
|
||||||
standard: `script/check` runs `script/test`, `script/lint` and
|
`script/bootstrap` first**, because the workflow checks out the repo and runs
|
||||||
`script/fmt-check`, then builds the image; `script/precommit` is what the git
|
nothing else, while `script/fmt-check` runs the formatter on the host: on a
|
||||||
|
pristine checkout with nothing installed the run dies there, after the
|
||||||
|
containerised gates have passed. **The bootstrap alone is not enough**:
|
||||||
|
`script/bootstrap` installs node and yarn under nvm and leaves neither on the
|
||||||
|
`PATH` of the shell that called it, so a bare `yarn` still exits 127. The host
|
||||||
|
entrypoints that need yarn — `script/fmt` and `script/fmt-check` — therefore
|
||||||
|
source nvm for the pinned node version before invoking it, exactly as
|
||||||
|
`script/bootstrap`'s own install step does. A runner carrying nothing but
|
||||||
|
docker and git then gets through `script/check`. Four further scripts are our
|
||||||
|
own extensions to the standard: `script/check` runs `script/test`,
|
||||||
|
`script/lint` and `script/fmt-check`; `script/precommit` is what the git
|
||||||
pre-commit hook runs, and it calls `script/check`; `script/install-precommit`
|
pre-commit hook runs, and it calls `script/check`; `script/install-precommit`
|
||||||
installs the git pre-commit hook (the `make hooks` target shims to it); and
|
installs the git pre-commit hook (the `make hooks` target shims to it); and
|
||||||
`script/projectname` (literally that filename) simply outputs the project's
|
`script/projectname` (literally that filename) simply outputs the project's
|
||||||
@@ -115,7 +125,7 @@ style conventions are in separate documents:
|
|||||||
plain `docker build .` builds the last stage alone and exits 0 having linted
|
plain `docker build .` builds the last stage alone and exits 0 having linted
|
||||||
and tested nothing.
|
and tested nothing.
|
||||||
|
|
||||||
**Every `docker build` in `script/` is tagged**, here and in `script/check`,
|
**Every `docker build` in `script/` is tagged**, here and in
|
||||||
`script/cibuild` and `script/docker`. An untagged build leaves a dangling
|
`script/cibuild` and `script/docker`. An untagged build leaves a dangling
|
||||||
image behind on every invocation, on every developer host and every CI
|
image behind on every invocation, on every developer host and every CI
|
||||||
runner; a tagged one replaces the previous image.
|
runner; a tagged one replaces the previous image.
|
||||||
@@ -139,14 +149,13 @@ style conventions are in separate documents:
|
|||||||
- **Any build that runs checks is built with `--no-cache`.** Docker invalidates
|
- **Any build that runs checks is built with `--no-cache`.** Docker invalidates
|
||||||
a `COPY` layer only when the copied content changes, so on an unchanged tree
|
a `COPY` layer only when the copied content changes, so on an unchanged tree
|
||||||
the check `RUN` is served from cache, nothing executes, and the build still
|
the check `RUN` is served from cache, nothing executes, and the build still
|
||||||
exits 0. `script/lint`, `script/test`, `script/cibuild` and `script/docker`
|
exits 0. Every `docker build` in `script/` therefore passes `--no-cache`:
|
||||||
therefore pass `--no-cache`, and a bare `docker build .` is not evidence that
|
`script/lint`, `script/test`, `script/cibuild` and `script/docker` are the
|
||||||
anything ran: a sub-second build reporting success is a cache hit, not a
|
four, and there is no fifth — `script/check` runs the two gate phases and
|
||||||
result. The one build that may go through the cache is the image build inside
|
`script/fmt-check`, and builds no image of its own. A bare `docker build .` is
|
||||||
`script/check`, which runs immediately after the two gate phases were built
|
not evidence that anything ran: a sub-second build reporting success is a
|
||||||
uncached and so reuses that run. Never invalidate by pruning —
|
cache hit, not a result. Never invalidate by pruning — `docker builder prune`
|
||||||
`docker builder prune` and friends destroy a build cache shared with every
|
and friends destroy a build cache shared with every other build on the host.
|
||||||
other build on the host.
|
|
||||||
|
|
||||||
- **The gate phases are separate stages, and the build stage depends on both.**
|
- **The gate phases are separate stages, and the build stage depends on both.**
|
||||||
The lint phase is based on the `golangci/golangci-lint` image (pinned by
|
The lint phase is based on the `golangci/golangci-lint` image (pinned by
|
||||||
@@ -218,10 +227,13 @@ style conventions are in separate documents:
|
|||||||
`script/docker` and `script/cibuild`; no stage may call `git describe`.
|
`script/docker` and `script/cibuild`; no stage may call `git describe`.
|
||||||
|
|
||||||
- Every repo should have a Gitea Actions workflow (`.gitea/workflows/`) that
|
- Every repo should have a Gitea Actions workflow (`.gitea/workflows/`) that
|
||||||
runs `script/cibuild` on push. That script runs the gate phases and then the
|
runs `script/cibuild` on push, and checks out the repo as its only other step.
|
||||||
image build, so a successful run means every check passed; a bare
|
That script bootstraps, runs the gate phases, and then builds the image, so a
|
||||||
`docker build .` does not carry the same guarantee, because its gate phases
|
successful run means every check passed; a bare `docker build .` does not
|
||||||
may come from the cache.
|
carry the same guarantee, because its gate phases may come from the cache. The
|
||||||
|
image build is uncached and so runs the gate phases a second time. That is the
|
||||||
|
price of the rule above, and it is worth paying: the image that ships is built
|
||||||
|
from a run of its own gates rather than from a cache entry.
|
||||||
|
|
||||||
- Use platform-standard formatters: `black` for Python, `prettier` for
|
- Use platform-standard formatters: `black` for Python, `prettier` for
|
||||||
JS/CSS/Markdown/HTML, `go fmt` for Go. Always use default configuration with
|
JS/CSS/Markdown/HTML, `go fmt` for Go. Always use default configuration with
|
||||||
@@ -268,11 +280,24 @@ style conventions are in separate documents:
|
|||||||
|
|
||||||
```makefile
|
```makefile
|
||||||
test:
|
test:
|
||||||
@go test -timeout 90s -race -cover ./... || \
|
@go test -count=1 -timeout 90s -race -cover ./... || \
|
||||||
{ echo "--- Rerunning with -v for details ---"; \
|
{ echo "--- Rerunning with -v for details ---"; \
|
||||||
go test -timeout 90s -race -v ./...; exit 1; }
|
go test -count=1 -timeout 90s -race -v ./...; exit 1; }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`-count=1` is required on both invocations: it defeats Go's test _result_
|
||||||
|
cache, so the target cannot report a pass it did not earn, and the rerun
|
||||||
|
reproduces a failure instead of replaying it. It leaves the build cache
|
||||||
|
alone, so it costs the runtime of the suite and no recompilation.
|
||||||
|
|
||||||
|
Note that this is a second, independent cache, stacked below the Docker
|
||||||
|
layer cache that [issue #26](https://git.eeqj.de/sneak/prompts/issues/26)
|
||||||
|
addresses. `CHECK_EPOCH` guarantees the `RUN make test` _step_ re-executes;
|
||||||
|
it does not guarantee `go test` inside that step does any work, because the
|
||||||
|
`GOCACHE` baked into earlier image layers survives into the re-executed
|
||||||
|
step. They are two separate defects requiring two separate fixes, and a fix
|
||||||
|
for one must not be recorded as covering the other.
|
||||||
|
|
||||||
Python example:
|
Python example:
|
||||||
|
|
||||||
```makefile
|
```makefile
|
||||||
@@ -352,7 +377,9 @@ style conventions are in separate documents:
|
|||||||
# trip `set -e`, so the inline form degrades to an empty constant.
|
# trip `set -e`, so the inline form degrades to an empty constant.
|
||||||
version="$(git describe --tags --always --dirty 2>/dev/null || true)"
|
version="$(git describe --tags --always --dirty 2>/dev/null || true)"
|
||||||
[ -n "$version" ] || version="unknown"
|
[ -n "$version" ] || version="unknown"
|
||||||
docker build --no-cache --build-arg VERSION="$version" .
|
docker build --no-cache \
|
||||||
|
--build-arg VERSION="$version" \
|
||||||
|
-t "$(script/projectname)" .
|
||||||
```
|
```
|
||||||
|
|
||||||
`--always` makes an untagged repo yield an abbreviated commit hash rather
|
`--always` makes an untagged repo yield an abbreviated commit hash rather
|
||||||
|
|||||||
+4
-10
@@ -1,22 +1,16 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# script/check: run all checks (test, lint, fmt-check) and then the
|
# script/check: run all checks (test, lint, fmt-check). Our own
|
||||||
# image build. Our own extension to scripts-to-rule-them-all. test and
|
# extension to scripts-to-rule-them-all. test and lint are Docker
|
||||||
# lint are Docker phases; fmt-check is native, because a formatter
|
# phases; fmt-check is native, because a formatter writes the working
|
||||||
# writes the working tree. Must not modify any files.
|
# tree. Must not modify any files.
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
||||||
ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)"
|
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
"$SCRIPT_DIR/test"
|
"$SCRIPT_DIR/test"
|
||||||
"$SCRIPT_DIR/lint"
|
"$SCRIPT_DIR/lint"
|
||||||
"$SCRIPT_DIR/fmt-check"
|
"$SCRIPT_DIR/fmt-check"
|
||||||
# No --no-cache here: the two phases this build depends on were just
|
|
||||||
# built uncached above, so what it reuses is that run and not an
|
|
||||||
# older one.
|
|
||||||
cd "$ROOT"
|
|
||||||
docker build -t "$("$SCRIPT_DIR/projectname")" .
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|||||||
+9
-5
@@ -1,7 +1,10 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# script/cibuild: run the CI build. script/check runs the gates and
|
# script/cibuild: run the CI build. It bootstraps first: a CI runner
|
||||||
# builds the image; this repeats the build with the version, which
|
# checks out and runs this and nothing else, and script/fmt-check runs
|
||||||
# reuses the phases just built rather than re-running them.
|
# the formatter on the host, which a pristine checkout cannot do.
|
||||||
|
# --no-cache for the same reason as script/docker: the gate phases the
|
||||||
|
# final stage depends on are RUN steps, and a cached one is a check that
|
||||||
|
# did not run.
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
||||||
@@ -9,6 +12,8 @@ ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)"
|
|||||||
|
|
||||||
main() {
|
main() {
|
||||||
cd "$ROOT"
|
cd "$ROOT"
|
||||||
|
"$SCRIPT_DIR/bootstrap"
|
||||||
|
"$SCRIPT_DIR/check"
|
||||||
# Own line: a failing command substitution inside an argument does
|
# Own line: a failing command substitution inside an argument does
|
||||||
# not trip `set -e`, so the inline form degrades silently to an
|
# not trip `set -e`, so the inline form degrades silently to an
|
||||||
# empty constant. VERSION is computed here because .dockerignore
|
# empty constant. VERSION is computed here because .dockerignore
|
||||||
@@ -16,8 +21,7 @@ main() {
|
|||||||
# version without failing.
|
# version without failing.
|
||||||
version="$(git describe --tags --always --dirty 2>/dev/null || true)"
|
version="$(git describe --tags --always --dirty 2>/dev/null || true)"
|
||||||
[ -n "$version" ] || version="unknown"
|
[ -n "$version" ] || version="unknown"
|
||||||
"$SCRIPT_DIR/check"
|
docker build --no-cache \
|
||||||
docker build \
|
|
||||||
--build-arg VERSION="$version" \
|
--build-arg VERSION="$version" \
|
||||||
-t "$("$SCRIPT_DIR/projectname")" .
|
-t "$("$SCRIPT_DIR/projectname")" .
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -1,9 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# script/docker: build the Docker image tagged with the project name.
|
# script/docker: build the Docker image tagged with the project name.
|
||||||
# Identical in all repos; the tag comes from script/projectname.
|
# Identical in all repos; the tag comes from script/projectname.
|
||||||
# --no-cache because this is a standalone entrypoint: the lint and test
|
# --no-cache because the gate phases the final stage depends on are RUN
|
||||||
# phases the final stage depends on must run rather than be served from
|
# steps, and a cached one is a check that did not run.
|
||||||
# an older build.
|
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
||||||
|
|||||||
+20
-1
@@ -4,9 +4,28 @@ set -eu
|
|||||||
|
|
||||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
|
# Must match the pin in script/bootstrap.
|
||||||
|
NODE_VERSION="22.17.0"
|
||||||
|
|
||||||
|
# script/bootstrap installs node and yarn under nvm and leaves neither
|
||||||
|
# on the PATH of the shell that called it, so resolve the pinned
|
||||||
|
# toolchain here the way bootstrap's own install step does. nvm is a
|
||||||
|
# bash script, hence the subshell.
|
||||||
|
run_yarn() {
|
||||||
|
if command -v yarn >/dev/null 2>&1; then
|
||||||
|
exec yarn "$@"
|
||||||
|
fi
|
||||||
|
if [ ! -s "$HOME/.nvm/nvm.sh" ]; then
|
||||||
|
echo "fmt: no yarn; run script/bootstrap first" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
exec bash -c '. "$HOME/.nvm/nvm.sh" && nvm use "$1" >/dev/null &&
|
||||||
|
shift && exec yarn "$@"' bash "$NODE_VERSION" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
cd "$ROOT"
|
cd "$ROOT"
|
||||||
yarn run prettier --write '**/*.md' --tab-width 4 --prose-wrap always
|
run_yarn run prettier --write '**/*.md' --tab-width 4 --prose-wrap always
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|||||||
+20
-1
@@ -4,9 +4,28 @@ set -eu
|
|||||||
|
|
||||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
|
# Must match the pin in script/bootstrap.
|
||||||
|
NODE_VERSION="22.17.0"
|
||||||
|
|
||||||
|
# script/bootstrap installs node and yarn under nvm and leaves neither
|
||||||
|
# on the PATH of the shell that called it, so resolve the pinned
|
||||||
|
# toolchain here the way bootstrap's own install step does. nvm is a
|
||||||
|
# bash script, hence the subshell.
|
||||||
|
run_yarn() {
|
||||||
|
if command -v yarn >/dev/null 2>&1; then
|
||||||
|
exec yarn "$@"
|
||||||
|
fi
|
||||||
|
if [ ! -s "$HOME/.nvm/nvm.sh" ]; then
|
||||||
|
echo "fmt-check: no yarn; run script/bootstrap first" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
exec bash -c '. "$HOME/.nvm/nvm.sh" && nvm use "$1" >/dev/null &&
|
||||||
|
shift && exec yarn "$@"' bash "$NODE_VERSION" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
cd "$ROOT"
|
cd "$ROOT"
|
||||||
yarn run prettier --check '**/*.md' --tab-width 4 --prose-wrap always
|
run_yarn run prettier --check '**/*.md' --tab-width 4 --prose-wrap always
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|||||||
Reference in New Issue
Block a user