Repository navigation
Expand file tree
/
Copy pathTaskfile.yml
More file actions
138 lines (125 loc) · 6.84 KB
/
Copy pathTaskfile.yml
File metadata and controls
138 lines (125 loc) · 6.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# go-tools - the Go the spin-stack repositories build with, and nothing any of them ships.
#
# task test the Go tests, under the race detector, held to a coverage floor
# task lint golangci-lint with spin's rules, at spin's version, this repository's own
# gates run on itself: ctxlife, testquality, refs, sfw, taskgate, and actionlint
# task mutate break what the change against BASE (origin/main) touched, and ask the tests
# task coverage coverage.out's numbers, to the terminal or the workflow run's summary
# task versions which pins in versions.yaml are behind; task bump NAME=... moves one
# task site the documentation site under site/, built into site/dist
version: '3'
silent: true
vars:
OUT: '{{.ROOT_DIR}}/_output'
VERSIONS: go run ./cmd/versions
OWNER:
sh: echo "$(id -u):$(id -g)"
tasks:
test:
desc: The Go tests, under the race detector, with their coverage in coverage.out and held to a floor.
vars:
# Below today's 61.4%. Raise it when the number has moved up and stayed; never lower it to
# let a change through, or it is a gate that reports whatever it is given.
COVERAGE_FLOOR: 60
cmds:
- go test -race -covermode=atomic -coverprofile=coverage.out ./...
# The anchor makes it the total line, not a function with "total" in its name.
- |
total=$(go tool cover -func=coverage.out | awk '/^total:/ {print $3}' | tr -d '%')
awk -v got="$total" -v floor={{.COVERAGE_FLOOR}} 'BEGIN {
if (got + 0 < floor + 0) { printf "coverage is %s%%, below the floor of %s%%\n", got, floor; exit 1 }
printf "coverage: %s%% (floor %s%%)\n", got, floor
}'
lint:
desc: golangci-lint with spin's rules (.golangci.yml), at spin's version, over the Go.
cmds:
# As this user, on this host's module and build caches: the container fetches nothing a
# build here has not, and leaves nothing root's behind. Its own cache is under _output.
# GOTOOLCHAIN=local: the linter reads the code with the Go its image carries; go.mod's
# toolchain line is what builds and tests run under, and fetching it in here has no sumdb.
- mkdir -p {{.OUT}}/golangci-lint
- >-
docker run --rm -u {{.OWNER}} -v {{.ROOT_DIR}}:/work -w /work
-v "$(go env GOMODCACHE)":/go/pkg/mod -v "$(go env GOCACHE)":/cache/go-build
-e GOMODCACHE=/go/pkg/mod -e GOCACHE=/cache/go-build -e GOLANGCI_LINT_CACHE=/work/_output/golangci-lint
-e HOME=/tmp -e GOTOOLCHAIN=local
$({{.VERSIONS}} ref golangci-lint) golangci-lint run ./...
# What this repository gives the others, held to itself first.
- go run ./cmd/ctxlife
- go run ./cmd/testquality ./...
- go run ./cmd/refs
- go run ./cmd/mutate -stale-exempts
- go run ./cmd/sfw check
- go run ./cmd/taskgate -allow .github/taskgate-allow.txt
# A vulnerability the code calls and that has a fix fails, the standard library's too: the
# answer is the upgrade. It asks vuln.go.dev, so lint needs the network.
- go run ./cmd/vulngate ./...
# The trusted root every repository verifies with is renewed here, the day Sigstore moves.
- go run ./cmd/trustroot -check
- task: lint:workflows
lint:workflows:
desc: actionlint over .github/, and every action pinned by its commit.
cmds:
# -shellcheck= because actionlint runs whatever shellcheck is on PATH: a runner has one and
# a laptop may not, and a gate whose answer depends on the machine is not a gate.
- go run github.com/rhysd/actionlint/cmd/actionlint@$({{.VERSIONS}} version actionlint) -shellcheck=
# A tag is whatever its owner points it at; the comment is the version Dependabot moves.
- cmd: |
if grep -rnE '^\s*(- )?uses: [^./][^ ]*@' .github | grep -vE '@[0-9a-f]{40} # v[0-9]'; then
echo "an action above is used by a tag its owner can move: pin it by commit SHA, with '# vX.Y.Z' after it"
exit 1
fi
mutate:
desc: Break what the change against BASE touched and fail on an edit no test refuses (BASE=origin/main; in CI, what the run's event diffs against).
cmds:
# In a workflow, the base is the event's: a pull request's is what it merges into, a push's
# what the branch was before it (BEFORE, which the workflow hands in), or the commit before
# when that is not in the clone - a branch's first push.
- |
base="{{.BASE}}"
if [ -z "$base" ] && [ "${GITHUB_EVENT_NAME:-}" = pull_request ]; then
base="origin/$GITHUB_BASE_REF"
elif [ -z "$base" ] && [ -n "${GITHUB_ACTIONS:-}" ]; then
base="${BEFORE:-}"
git rev-parse --verify -q "$base^{commit}" >/dev/null || base=HEAD~1
fi
go run ./cmd/mutate -base "${base:-origin/main}" -max 200
coverage:
desc: Write coverage.out's total and per-function numbers to the run's summary ($GITHUB_STEP_SUMMARY, or the terminal) and coverage.html.
cmds:
- |
out="${GITHUB_STEP_SUMMARY:-/dev/stdout}"
[ -f coverage.out ] || { echo "coverage.out was not produced; the tests may have failed before coverage ran." >> "$out"; exit 0; }
func=$(go tool cover -func=coverage.out)
printf '## Go coverage\n\n**%s** total\n\n<details><summary>Function detail</summary>\n\n```\n%s\n```\n</details>\n' "$(awk '/^total:/ {print $3}' <<< "$func")" "$func" >> "$out"
go tool cover -html=coverage.out -o coverage.html
site:
desc: Build the documentation site (site/, Astro Starlight) into site/dist; task site:dev serves it with live reload.
cmds:
# From the root, where ./cmd/sfw is: site/ is a module of its own (site/go.mod says why).
- go run ./cmd/sfw pnpm --dir site install --frozen-lockfile
- pnpm --dir site build
site:dev:
desc: Serve the documentation site with live reload.
cmds:
- go run ./cmd/sfw pnpm --dir site install --frozen-lockfile
- pnpm --dir site dev
versions:
desc: Say which of versions.yaml's pins are behind their upstream, and of those cmd/sfw and cmd/exposure carry (exits 1 when any is).
cmds:
# Every file, whichever is behind: the others are the pins go tool sfw and go tool exposure
# embed for every repository.
- |
status=0
{{.VERSIONS}} check || status=1
{{.VERSIONS}} check -file cmd/sfw/versions.yaml || status=1
{{.VERSIONS}} check -file cmd/exposure/versions.yaml || status=1
exit $status
bump:
desc: Pin one entry of versions.yaml at a version, the newest by default (task bump NAME=golangci-lint [VERSION=v2.14.0]; FILE=cmd/sfw/versions.yaml or cmd/exposure/versions.yaml for what those commands embed).
requires:
vars: [NAME]
vars:
FILE: '{{.FILE | default "versions.yaml"}}'
cmds:
- '{{.VERSIONS}} bump -file {{.FILE}} {{.NAME}} {{.VERSION}}'