-
Notifications
You must be signed in to change notification settings - Fork 0
115 lines (108 loc) · 4.35 KB
/
Copy pathrelease.yml
File metadata and controls
115 lines (108 loc) · 4.35 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
name: Release
# Cutting a release is a tag push. A bare `vX.Y.Z` tag releases the primary
# module (state); a `module/vX.Y.Z` tag releases that submodule. The workflow
# re-runs the full validation gate for the tagged module, then publishes a
# GitHub release with generated notes.
on:
push:
tags:
# A bare "vX.Y.Z" releases the primary module (state). A nested
# "<module>/vX.Y.Z" releases that submodule; "**" matches any path depth,
# so two-segment module tags like "telemetry/otel/v0.1.0" trigger too (a
# single "*" never crosses "/", so it would miss them).
- "v*.*.*"
- "**/v*.*.*"
# Read-only by default; the publish job opts into contents:write explicitly.
permissions:
contents: read
env:
GOLANGCI_LINT: github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.12.2
GOVULNCHECK: golang.org/x/vuln/cmd/govulncheck@v1.3.0
# Run every step under bash on all runners, including Windows. Windows runners
# default to PowerShell, where `$GOVULNCHECK` / `$GOLANGCI_LINT` expand to empty
# and the go-run steps fail; bash makes interpolation consistent across the OS matrix.
defaults:
run:
shell: bash
jobs:
# Resolve which module directory the tag targets, and the tag string itself,
# from the trusted github context (never from user-controlled input).
resolve:
runs-on: ubuntu-latest
outputs:
module: ${{ steps.resolve.outputs.module }}
env:
REF_NAME: ${{ github.ref_name }}
steps:
- name: Resolve module from tag
id: resolve
run: |
# "module/vX.Y.Z" -> module ; bare "vX.Y.Z" -> state (primary module).
if printf '%s' "$REF_NAME" | grep -q '/'; then
module="${REF_NAME%/*}"
else
module="state"
fi
echo "module=$module" >> "$GITHUB_OUTPUT"
echo "Releasing module '$module' from tag '$REF_NAME'." >> "$GITHUB_STEP_SUMMARY"
# Full validation gate for the tagged module: lint, race tests, vuln scan, and
# the per-module coverage threshold. A tag must not publish unless it is green.
validate:
needs: resolve
strategy:
fail-fast: false
matrix:
go: ["1.25.11", "1.26.4"]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
env:
MODULE: ${{ needs.resolve.outputs.module }}
THRESHOLD: "80"
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: ${{ matrix.go }}
cache-dependency-path: "**/go.sum"
# Skip the Go cache save on Windows: the tar/zstd cache-save post-step
# flakes intermittently on windows-latest and fails the job even when
# tests pass. Linux and macOS keep caching.
cache: ${{ runner.os != 'Windows' }}
- name: test -race
working-directory: ${{ env.MODULE }}
run: go test -race ./...
- name: govulncheck
working-directory: ${{ env.MODULE }}
run: go run "$GOVULNCHECK" ./...
- name: golangci-lint
working-directory: ${{ env.MODULE }}
run: go run "$GOLANGCI_LINT" run --config "$GITHUB_WORKSPACE/.golangci.yml" ./...
- name: coverage gate
working-directory: ${{ env.MODULE }}
shell: bash
run: |
go test -covermode=atomic -coverprofile=coverage.out ./...
pct=$(go tool cover -func=coverage.out | awk '/^total:/ {sub(/%/,"",$3); print $3}')
echo "total coverage: ${pct}% (threshold ${THRESHOLD}%)"
awk -v p="$pct" -v t="$THRESHOLD" 'BEGIN { exit (p+0 < t+0) ? 1 : 0 }' \
|| { echo "::error::coverage ${pct}% is below the ${THRESHOLD}% threshold"; exit 1; }
# Publish only after the gate is fully green. This is the single job granted
# contents:write, and the only one that touches the GitHub release API.
publish:
needs: [resolve, validate]
runs-on: ubuntu-latest
permissions:
contents: write
env:
TAG: ${{ github.ref_name }}
GH_TOKEN: ${{ github.token }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
fetch-depth: 0
- name: Publish GitHub release
run: |
gh release create "$TAG" \
--title "$TAG" \
--generate-notes \
--verify-tag