Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f1b3f9fb7 |
+2
-8
@@ -50,12 +50,7 @@ ARG CHECK_EPOCH
|
||||
|
||||
COPY . .
|
||||
|
||||
# This cache mount keeps Go's build cache between builds for make test and
|
||||
# make build; -count=1 in script/test keeps test results out of it. Go's cache
|
||||
# does not notice C header changes, so the mount has its own id: change the id
|
||||
# when the C packages installed above change.
|
||||
RUN --mount=type=cache,id=sneak/secret/go-build,target=/root/.cache/go-build \
|
||||
make test
|
||||
RUN make test
|
||||
|
||||
# The version stamped into the binary: the VERSION build argument when one
|
||||
# is given, otherwise `git describe --tags --always` of the .git the build
|
||||
@@ -63,8 +58,7 @@ RUN --mount=type=cache,id=sneak/secret/go-build,target=/root/.cache/go-build \
|
||||
# one, the short commit when no tag is reachable. A context that carries .git
|
||||
# and still yields no version fails the build.
|
||||
ARG VERSION
|
||||
RUN --mount=type=cache,id=sneak/secret/go-build,target=/root/.cache/go-build \
|
||||
version="${VERSION:-$(git describe --tags --always)}"; \
|
||||
RUN version="${VERSION:-$(git describe --tags --always)}"; \
|
||||
if [ -e .git ] && { [ -z "$version" ] || [ "$version" = dev ] || \
|
||||
[ "$version" = unknown ]; }; then \
|
||||
echo "no version could be derived although the build context carries .git" >&2; \
|
||||
|
||||
@@ -604,8 +604,7 @@ provide:
|
||||
- `script/build` — build the `secret` binary into the repo root, stamping the
|
||||
version (`VERSION` from the environment, else `git describe`) and the git
|
||||
commit
|
||||
- `script/test` — run `go vet` and the test suite (verbose rerun on failure),
|
||||
every test on every run, never a result from Go's test cache
|
||||
- `script/test` — run `go vet` and the test suite (verbose rerun on failure)
|
||||
- `script/lint` — run `golangci-lint` in docker only: builds `Dockerfile.lint`,
|
||||
where the linter is a build step that runs on every call, also on an unchanged
|
||||
tree
|
||||
@@ -625,8 +624,7 @@ provide:
|
||||
- `script/cibuild` — CI entrypoint: `docker build --ulimit memlock=-1:-1 .`
|
||||
(memguard needs mlock; the Dockerfile runs the checks), with a new
|
||||
`CHECK_EPOCH` build argument on every run so the checks run again on an
|
||||
unchanged tree; the `Dockerfile` keeps Go's build cache between builds, so
|
||||
`make test` and `make build` compile only what changed
|
||||
unchanged tree
|
||||
- `script/precommit` — pre-commit checks: `go mod tidy` verification, then
|
||||
`script/check`
|
||||
- `script/install-precommit` — install the git pre-commit hook that runs
|
||||
|
||||
@@ -18,16 +18,18 @@ https://git.eeqj.de/sneak/secret/milestone/12
|
||||
|
||||
# Completed Steps
|
||||
|
||||
- 2026-10-06: `make test` in `script/cibuild` no longer compiles the standard
|
||||
library and every dependency from nothing on every build
|
||||
(https://git.eeqj.de/sneak/secret/issues/124). The `Dockerfile` runs it and
|
||||
`make build` with Go's build cache in a BuildKit cache mount, which docker
|
||||
keeps between builds, so each compiles only what changed since the last build.
|
||||
The mount has an id of its own, so other repositories' builds do not share it.
|
||||
`script/test` passes `-count=1`, so every test runs on every build and no
|
||||
result comes from Go's test cache. A build with an empty cache, such as the
|
||||
first after docker's build cache is cleared, compiles everything in
|
||||
`make test` as before.
|
||||
- 2026-10-06: `TestRemoveIgnoresTerminalOnStdout` and
|
||||
`TestRemoveAsksAtTerminalOnStdin` no longer wait until Go's test timeout
|
||||
(https://git.eeqj.de/sneak/secret/issues/126). On Linux, `pty.Open` of
|
||||
`github.com/creack/pty` v1.1.24 passed the address of a local variable to the
|
||||
`ioctl` system call as a plain number, through a function call; when Go moved
|
||||
the goroutine's stack in between, the kernel wrote the terminal's number to
|
||||
the old place, and `pty.Open` opened `/dev/pts/0` instead of the terminal it
|
||||
had created. `secret rm` then wrote to that other terminal, and the test read
|
||||
a terminal no program had open, which never ends. `go.mod` now requires the
|
||||
commit on that library's main branch that passes a pointer instead; no release
|
||||
has it yet. Both tests stop reading the terminal when their one-minute context
|
||||
ends and fail saying so.
|
||||
- 2026-10-06: The tests run quickly with the race detector on
|
||||
(https://git.eeqj.de/sneak/secret/issues/120). Most of their time went to
|
||||
deriving keys from passphrases with scrypt, which is slow on purpose. The new
|
||||
|
||||
@@ -9,7 +9,7 @@ require (
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.1.3
|
||||
github.com/btcsuite/btcd/btcutil v1.1.6
|
||||
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d
|
||||
github.com/creack/pty v1.1.24
|
||||
github.com/creack/pty v1.1.25-0.20260601142114-9246436fffe8 // v1.1.24's Open can return another pty's terminal
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/fatih/color v1.18.0
|
||||
github.com/keybase/go-keychain v0.0.0-20230307172405-3e4884637dd1
|
||||
|
||||
@@ -35,8 +35,8 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg
|
||||
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
|
||||
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
|
||||
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
|
||||
github.com/creack/pty v1.1.25-0.20260601142114-9246436fffe8 h1:CY3gjC7naqYGLMiywvj3suPfa1i0p/QEr7o8ujxL/2M=
|
||||
github.com/creack/pty v1.1.25-0.20260601142114-9246436fffe8/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
|
||||
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
||||
@@ -2601,7 +2601,9 @@ func TestRemoveWithoutTerminalFailsAtOnce(t *testing.T) {
|
||||
// and stderr, not both: whether it asks must depend on stdin alone, where
|
||||
// the answer is read from. pty.Open returns the two ends of a new terminal:
|
||||
// tty is the end a program uses as its terminal, and ptmx the end the test
|
||||
// reads what the terminal shows from and types into.
|
||||
// reads what the terminal shows from and types into. Reading ptmx stops at
|
||||
// the context's deadline, when secret rm is killed too, so a terminal that
|
||||
// stays open fails the test then instead of hanging it.
|
||||
|
||||
// TestRemoveIgnoresTerminalOnStdout runs `echo y | secret rm x` at a
|
||||
// terminal. stdin is a pipe, so nobody can answer there, and the command
|
||||
@@ -2619,6 +2621,9 @@ func TestRemoveIgnoresTerminalOnStdout(t *testing.T) {
|
||||
|
||||
defer func() { _ = ptmx.Close() }()
|
||||
|
||||
deadline, _ := ctx.Deadline()
|
||||
require.NoError(t, ptmx.SetReadDeadline(deadline))
|
||||
|
||||
cmd.Stdin = strings.NewReader("y\n")
|
||||
cmd.Stdout = tty
|
||||
cmd.Stderr = tty
|
||||
@@ -2628,9 +2633,15 @@ func TestRemoveIgnoresTerminalOnStdout(t *testing.T) {
|
||||
_ = tty.Close()
|
||||
|
||||
// The read ends once secret rm has exited and so closed the terminal.
|
||||
shown, _ := io.ReadAll(ptmx)
|
||||
shown, err := io.ReadAll(ptmx)
|
||||
require.NotErrorIs(t, err, os.ErrDeadlineExceeded,
|
||||
"the terminal was still open a minute after secret rm started: %s",
|
||||
shown)
|
||||
|
||||
require.Error(t, cmd.Wait())
|
||||
err = cmd.Wait()
|
||||
|
||||
require.NoError(t, ctx.Err(), "secret rm did not exit within a minute")
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, string(shown), "pass --force")
|
||||
assert.DirExists(t, secretDir)
|
||||
}
|
||||
@@ -2650,6 +2661,9 @@ func TestRemoveAsksAtTerminalOnStdin(t *testing.T) {
|
||||
|
||||
defer func() { _ = ptmx.Close() }()
|
||||
|
||||
deadline, _ := ctx.Deadline()
|
||||
require.NoError(t, ptmx.SetReadDeadline(deadline))
|
||||
|
||||
cmd.Stdin = tty
|
||||
// Not a file, so exec.Cmd connects stdout through a pipe.
|
||||
cmd.Stdout = io.Discard
|
||||
@@ -2667,7 +2681,8 @@ func TestRemoveAsksAtTerminalOnStdin(t *testing.T) {
|
||||
terminal := bufio.NewReader(ptmx)
|
||||
for !bytes.HasSuffix(shown, []byte("[y/N] ")) {
|
||||
char, err = terminal.ReadByte()
|
||||
require.NoError(t, err, "secret rm ended without asking: %s", shown)
|
||||
require.NoError(t, err, "secret rm did not ask on the terminal: %s",
|
||||
shown)
|
||||
|
||||
shown = append(shown, char)
|
||||
}
|
||||
|
||||
+1
-2
@@ -6,8 +6,7 @@
|
||||
# the lower limit of a plain `docker build .`.
|
||||
# A cached build checks nothing: a new CHECK_EPOCH on every run makes the
|
||||
# Dockerfile's check steps run again on an unchanged tree, while its base
|
||||
# images, module downloads and the Go build cache that make test and make
|
||||
# build use stay cached.
|
||||
# images and module downloads stay cached.
|
||||
set -eu
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||
|
||||
+1
-3
@@ -9,9 +9,7 @@ main() {
|
||||
# CGO is required (Makefile exports this too)
|
||||
export CGO_ENABLED=1
|
||||
go vet ./...
|
||||
# -count=1: run every test, never take a result from Go's test cache,
|
||||
# which the Dockerfile keeps between builds
|
||||
go test -count=1 ./... || go test -count=1 -v ./...
|
||||
go test ./... || go test -v ./...
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
Reference in New Issue
Block a user