-
Notifications
You must be signed in to change notification settings - Fork 1
137 lines (120 loc) · 4.75 KB
/
Copy pathdeploy.yml
File metadata and controls
137 lines (120 loc) · 4.75 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
name: deploy
# Build + sign + publish a release artifact. PULL-BASED deploy:
# this workflow never touches the production box and never holds an SSH key.
# The box runs cosift-self-update.timer, which polls the latest GitHub Release,
# verifies sha256 + minisign signature against a public key baked on the box,
# atomically swaps the binary, restarts, and health-gates with
# auto-rollback. See deploy/scripts/README.md.
#
# Triggers:
# - push of a version tag (v*) → cut a release for that tag
# - manual workflow_dispatch → build from a chosen ref (no release
# unless a tag is also present)
on:
push:
tags:
- 'v*'
workflow_dispatch:
permissions:
contents: write # needed to create the GitHub Release + upload assets
jobs:
# (a) verify — gate the release on vet + race tests + a smoke subset.
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-go@v7
with:
go-version-file: go.mod
cache: true
- name: go vet
run: go vet ./...
- name: Tests (race)
run: go test -race -timeout 10m ./...
- name: Smoke subset (build + serve roundtrip)
# make smoke builds the binary, crawls, and asserts /healthz + /search.
# Guarded with a timeout so a hung crawl can't wedge the release.
run: timeout 300 make smoke
# (b) build — static server and CLI binaries, sha256, minisign signatures.
build:
needs: verify
runs-on: ubuntu-latest
outputs:
version: ${{ steps.ver.outputs.version }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0 # full history so version stamping is meaningful
- uses: actions/setup-go@v7
with:
go-version-file: go.mod
cache: true
- name: Resolve version stamp
id: ver
# Tag name when triggered by a tag push; otherwise the short SHA.
run: |
if [ "${GITHUB_REF_TYPE}" = "tag" ]; then
echo "version=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT"
else
echo "version=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
fi
- name: Build CLI and server binaries
env:
CGO_ENABLED: '0'
VERSION: ${{ steps.ver.outputs.version }}
run: |
mkdir -p dist
for target in linux/arm64 linux/amd64 darwin/arm64 darwin/amd64 windows/amd64; do
export GOOS="${target%/*}" GOARCH="${target#*/}"
name="cosift-${GOOS}-${GOARCH}"
if [ "$GOOS" = windows ]; then name="${name}.exe"; fi
go build -trimpath -ldflags "-s -w -X main.version=${VERSION} -X github.com/pilot-protocol/cosift/internal/server.Version=${VERSION}" -o "dist/$name" ./cmd/cosift
(cd dist && sha256sum "$name" > "$name.sha256")
done
- name: Install minisign
run: sudo apt-get update && sudo apt-get install -y minisign
- name: Sign with minisign
env:
# Repo secret. The matching PUBLIC key is baked on the box at
# /etc/cosift/minisign.pub. Generate with `minisign -G` (see
# deploy/scripts/README.md). NEVER commit the secret key.
MINISIGN_SECRET_KEY: ${{ secrets.MINISIGN_SECRET_KEY }}
run: |
if [ -z "${MINISIGN_SECRET_KEY}" ]; then
echo "::error::MINISIGN_SECRET_KEY secret is not set" >&2
exit 1
fi
printf '%s' "${MINISIGN_SECRET_KEY}" > minisign.key
# -W: secret key is unencrypted (no interactive passphrase prompt).
# Trusted comment carries the version so the box can sanity-check it.
for binary in dist/cosift-*; do
case "$binary" in *.sha256) continue;; esac
minisign -S -W -s minisign.key -m "$binary" -t "cosift ${{ steps.ver.outputs.version }} $(basename "$binary")"
done
rm -f minisign.key
- uses: actions/upload-artifact@v7
with:
name: cosift-release-artifacts
path: dist/*
retention-days: 30
# (c) release — publish the signed binary as a GitHub Release asset.
# Only on a tag push (workflow_dispatch builds the artifact but does not
# cut a release).
release:
needs: build
if: github.ref_type == 'tag'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/download-artifact@v8
with:
name: cosift-release-artifacts
- name: Create / update GitHub Release
uses: softprops/action-gh-release@v3
with:
tag_name: ${{ github.ref_name }}
name: cosift ${{ github.ref_name }}
generate_release_notes: true
fail_on_unmatched_files: true
files: cosift-*