diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c48fc3b..614dc8a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -30,6 +30,12 @@ jobs: - name: Lint run: make lint + # A zero exit does not prove a binary exists: + # widened to ./..., go build checks the command and writes nothing. + # Only the artifact proves it built. + - name: Build + run: make build && test -x bin/envrun + - name: Test and cover # We don't need the benchmarks to run for long, just enough for coverage. run: mkdir -p coverage; make cover diff --git a/.gitignore b/.gitignore index e169599..7d3c8ff 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,8 @@ /.env # Generated by "make demo" from the testdata fixtures. /.env.demo -# The command itself, when built in place by `go build ./...`. -/envrun +# Generated by "make build". +/bin/envrun # Created by "make cover". Only its *.out contents match a rule below, so the # directory itself needs one: anything else written there would be committed. /coverage/ diff --git a/Makefile b/Makefile index eeece5d..cf3246e 100644 --- a/Makefile +++ b/Makefile @@ -3,10 +3,11 @@ # A public repo also pays twice: contributors need a new tool, and CI, # which pins every action to a SHA, gains unpinned supply-chain surface. -all: lint build +all: lint test build -GO := go +BINDIR := bin COVERDIR := coverage +GO := go PACKAGES := ./... # If _RAW_GOBIN is empty, take the first element in _RAW_GOPATH @@ -23,7 +24,7 @@ GOBIN := $(if $(_RAW_GOBIN),$(_RAW_GOBIN),$(firstword $(subst :, ,$(subst ;, ,$( DEMO_ENV := .env.demo # Only the demo's own variables are shown: "env" prints the whole environment, -# so an unfiltered demo leaks whatever secrets the caller happens to export. +# so an unfiltered demo would leak whatever secrets the caller happens to export. demo: $(DEMO_ENV) @sed -nE 's/^[[:space:]]*([^#=[:space:]][^=]*[^=[:space:]]|[^#=[:space:]])[[:space:]]*=.*/^\1=/p' $(DEMO_ENV) > $(DEMO_ENV).names @LOCAL=demo $(GO) run . -f $(DEMO_ENV) env | grep -f $(DEMO_ENV).names | sort @@ -32,7 +33,7 @@ demo: $(DEMO_ENV) $(DEMO_ENV): $(wildcard env/testdata/pass-*.env) cat $^ > $@ -.PHONY: build clean cover demo install lint modernize test +.PHONY: all build clean cover demo install lint modernize test lint: modernize $(GO) tool staticcheck -checks=all $(PACKAGES) @@ -46,19 +47,21 @@ cover: mkdir -p $(COVERDIR) # This runs the benchmarks just once, as unit tests, for coverage reporting only. # It does not replace running "make bench". - $(GO) test -v -race -run=. -coverprofile=$(COVERDIR)/cover.out -covermode=atomic $(PACKAGES) + $(GO) test -v -race -coverprofile=$(COVERDIR)/cover.out -covermode=atomic $(PACKAGES) $(GO) tool cover -html=$(COVERDIR)/cover.out test: # This includes the fuzz tests in unit test mode $(GO) test -race $(PACKAGES) -build: test - $(GO) build $(PACKAGES) +# go build discards its result when handed more than one package, +# so $(PACKAGES) would check that the command builds without ever producing it. +build: + $(GO) build -o $(BINDIR)/ . -install: build +install: test build $(GO) install . clean: @echo GOBIN: $(GOBIN) - rm -fr $(COVERDIR) $(DEMO_ENV) envrun $(GOBIN)/envrun + rm -fr $(COVERDIR) $(DEMO_ENV) $(BINDIR)/envrun $(GOBIN)/envrun diff --git a/README.md b/README.md index 9d05021..77b18f3 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![GoDoc](https://pkg.go.dev/badge/github.com/fgm/envrun)](https://pkg.go.dev/github.com/fgm/envrun) [![CI](https://github.com/fgm/envrun/actions/workflows/tests.yml/badge.svg)](https://github.com/fgm/envrun/actions/workflows/tests.yml) [![codecov](https://codecov.io/gh/fgm/envrun/branch/main/graph/badge.svg?token=8YYX1B720M)](https://codecov.io/gh/fgm/envrun) -[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/fgm/envrun/badge)](https://securityscorecards.dev/viewer/?uri=github.com/fgm/envrun) +[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/fgm/envrun/badge)](https://scorecard.dev/viewer/?uri=github.com/fgm/envrun) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/14232/badge)](https://www.bestpractices.dev/projects/14232) The `envrun` command runs any command with default environment variables taken from a file, @@ -69,6 +69,8 @@ so keep values plain if both read it. The format, and what it refuses to carry, is in [The environment file](docs/environment-file.md). +In a clone, `make build` writes the binary to `bin/envrun`. + `make demo` builds a file from the parsing fixtures in `env/testdata/` and runs `env` against it. Those fixtures are what the test suite asserts against, so the demo cannot drift from the documented behaviour.