Repository navigation
254 lines (236 loc) · 9.03 KB
/
Copy pathgo-test.yml
File metadata and controls
254 lines (236 loc) · 9.03 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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
name: go-test
permissions:
pull-requests: read
contents: read
on:
workflow_call:
inputs:
extra-flags:
description: extra flags to add to go test
type: string
required: false
test-matrix:
description: |
Optional JSON string to define the test matrix, using keys: "os" and "go".
By default tests run a 6-way matrix running on os (linux,windows,macos)
for the 2 latest go releases (stable, oldstable).
The default matrix used is:
{"os":["ubuntu-latest","macos-latest","windows-latest"],"go": ["oldstable","stable"]}
type: string
required: false
no-race:
description: 'runs test without -race'
type: string
required: false
default: 'false'
timeout:
description: 'test timeout'
type: string
required: false
default: '30m'
extra-paths:
description: |
Extra glob patterns, one per line, that mark a change as relevant to the tests.
See the 'extra-paths' input of changed-paths.yml. Repositories with fixtures or a
codegen configuration outside of the go sources want to declare them here.
type: string
required: false
default: ''
force-run:
description: |
Set to 'true' to run the full matrix whatever changed, bypassing changed-paths detection.
Use it for scheduled or manually dispatched runs, and as the opt-out for repositories
that do not want path-based skipping.
type: string
required: false
default: 'false'
defaults:
run:
shell: bash
jobs:
changes:
# description: |
# Decide whether this run has anything to test. Fails open: anything unclear runs
# the whole suite. Skipped jobs cost no runner minute, but the workflow keeps
# reporting, so "tests completed" stays usable as a required status check.
name: Changes
uses: ./.github/workflows/changed-paths.yml
with:
preset: go
extra-paths: ${{ inputs.extra-paths }}
force: ${{ inputs.force-run }}
lint:
name: Lint
needs: [changes]
if: ${{ needs.changes.outputs.changed == 'true' }}
runs-on: ubuntu-latest
steps:
-
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: stable
check-latest: true
cache: true
-
name: golangci-lint
uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9.3.0
with:
version: latest
only-new-issues: true
skip-cache: true
test:
name: Unit tests
runs-on: ${{ matrix.os }}
needs: [changes, lint]
if: ${{ needs.changes.outputs.changed == 'true' }}
strategy:
# Read straight from the inputs: routing it through a job output would make the
# matrix depend on that job having run, and lint is now skippable.
#
# Mind the absence of a space after '"go":': a ": " sequence would end the plain
# YAML scalar and the whole expression would fail to parse.
matrix: ${{ fromJSON(inputs.test-matrix || '{"os":["ubuntu-latest","macos-latest","windows-latest"],"go":["oldstable","stable"]}') }}
steps:
-
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Ensure GOCACHE is created on windows runners
# On windows, the github runner locates the GOROOT and GOCACHE on C:, whereas our
# tests are executed on D:. We want to colocalize the cache.
if: ${{ runner.os == 'Windows' }}
shell: bash
env:
BASE: ${{ github.workspace }}
run: |
mkdir -p ../.cache/go-build
mkdir -p ../pkg/mod
_base=$(cygpath -u "${BASE}")
_gocache="$(realpath ${_base}/../.cache/go-build)"
_modcache="$(realpath ${_base}/../pkg/mod)"
GOCACHE=$(cygpath -w "${_gocache}")
GOMODCACHE=$(cygpath -w "${_modcache}")
#
echo "GOCACHE=${GOCACHE}" >> "${GITHUB_ENV}"
echo "GOMODCACHE=${GOMODCACHE}" >> "${GITHUB_ENV}"
echo "::gocache::${GOCACHE}"
echo "::gomodcache::${GOMODCACHE}"
-
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '${{ matrix.go }}'
check-latest: true
cache: true
-
name: Install gotestsum
uses: go-openapi/gh-actions/install/gotestsum@2a20802fd4ec9b9fd4732b832c91fec9c4aae777 # v1.4.20
-
name: Ensure TMP is created on windows runners
# On windows, some tests require testing.TempDir to reside on the same drive as the code.
# TMP is used by os.TempDir() to determine the location of temporary files.
if: ${{ runner.os == 'Windows' }}
shell: bash
env:
BASE: ${{ github.workspace }}
run: |
mkdir -p "${BASE}/../tmp"
_base=$(cygpath -u "${BASE}")
_tmp=$(realpath ${_base}/../tmp)
TMP=$(cygpath -w "${_tmp}")
#
echo "TMP=${TMP}" >> "${GITHUB_ENV}"
echo "::tmp::${TMP}"
-
name: Run unit tests
env:
EXTRA_FLAGS: ${{ inputs.extra-flags }}
WANTS_NORACE: ${{ inputs.no-race }}
TIMEOUT: ${{ inputs.timeout }}
run: |
RACEOPT="-race"
if [[ "${WANTS_NORACE}" == "true" ]] ; then
RACEOPT=""
fi
# ${RACEOPT} unquoted on purpose: quoted, an empty value passes '' as a package
# pattern, and go test then runs nothing and still exits 0.
gotestsum \
--jsonfile 'unit.report.${{ matrix.os }}-${{ matrix.go }}.json' \
-- \
${RACEOPT} \
-p 2 \
-count 1 \
-timeout="${TIMEOUT}" \
-coverprofile='unit.coverage.${{ matrix.os }}-${{ matrix.go }}.out' \
-covermode=atomic \
-coverpkg="$(go list)"/... ${EXTRA_FLAGS} \
./...
-
name: Upload coverage artifacts
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
# *.coverage.* pattern is automatically detected by codecov
path: '**/*.coverage.*.out'
name: 'unit.coverage.${{ matrix.os }}-${{ matrix.go }}'
retention-days: 1
-
name: Upload test report artifacts
# upload report even if test fail. BTW, this is when they are valuable.
if: ${{ !cancelled() }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
path: '**/unit.report.*.json'
name: 'unit.report.${{ matrix.os }}-${{ matrix.go }}'
retention-days: 1
fuzz-test:
needs: [changes]
if: ${{ needs.changes.outputs.changed == 'true' }}
uses: ./.github/workflows/fuzz-test.yml
test-complete:
# description: |
# Be explicit about all tests being passed. This allows for setting up only a few status checks on PRs.
#
# This is the gate: it is the one job callers pin in their branch protection rules, so it
# MUST report on every run, including the runs where everything else was skipped.
#
# Hence "always()" -- with the default condition the job would inherit the skip of its
# dependencies and never report, which is the very hole we are closing -- and an assertion
# on the negative: fail on 'failure' and 'cancelled', pass on 'skipped'. A job correctly
# skipped is then indistinguishable from a job that had nothing to do.
#
# Every job belongs in "needs", "changes" included: a job skipped because ITS dependency
# failed reports 'skipped', so leaving the failing one out would turn the gate green over
# an untested pull request.
name: tests completed
needs: [changes, lint, test, fuzz-test]
if: ${{ always() }}
runs-on: ubuntu-latest
steps:
-
name: Report upstream job results
env:
RESULTS: ${{ toJSON(needs) }}
run: |
echo "::group::upstream job results"
printenv RESULTS
echo "::endgroup::"
-
name: Fail on any unsuccessful upstream job
if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
run: |
echo "::error title=tests::at least one job failed or was cancelled"
exit 1
-
name: Tests completed
run: |
echo "::notice title=Success::All tests passed"
collect-coverage:
# Guarded on the tests themselves: "tests completed" is now green on runs where the
# matrix never ran, and there would be no coverage artifact to collect.
needs: [test]
if: ${{ !cancelled() && needs.test.result == 'success' }}
uses: ./.github/workflows/collect-coverage.yml
collect-reports:
needs: [test]
if: ${{ !cancelled() && needs.test.result != 'skipped' }}
uses: ./.github/workflows/collect-reports.yml