mirror of
https://github.com/juanfont/headscale.git
synced 2026-10-30 18:24:06 +09:00
1 parent
c285eff776
commit
beb1214926
4 files changed
+143
-1
No files matched your search
@@ -0,0 +1,35 @@
|
||||
name: Release checks
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: nix develop --fallback --command bash -e {0}
|
||||
|
||||
jobs:
|
||||
release-check:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: NixOS/nix-installer-action@62c1943b776c509394b550f3f983adc14e9212d6 # main
|
||||
- uses: Mic92/hestia@dfed9ced335d28978ba74e513939a10db1f71025 # v3.1.0
|
||||
- name: Validate release configuration
|
||||
run: goreleaser check
|
||||
- name: Test release guards
|
||||
run: bash tools/release-check-test.sh
|
||||
- name: Build and verify Headscale release binary
|
||||
run: goreleaser build --snapshot --clean --single-target
|
||||
+3
-1
@@ -2,7 +2,6 @@
|
||||
version: 2
|
||||
before:
|
||||
hooks:
|
||||
- go mod tidy
|
||||
- go mod vendor
|
||||
|
||||
release:
|
||||
@@ -27,6 +26,9 @@ builds:
|
||||
- linux_arm64
|
||||
flags:
|
||||
- -mod=readonly
|
||||
hooks:
|
||||
pre: bash tools/release-check.sh
|
||||
post: bash tools/release-check.sh "{{ .Path }}"
|
||||
|
||||
archives:
|
||||
- id: golang-cross
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
root=$(cd "$(dirname "$0")/.." && pwd)
|
||||
tmp=$(mktemp -d)
|
||||
trap 'rm -rf "$tmp"' EXIT
|
||||
export GOWORK=off CGO_ENABLED=0 LC_ALL=C
|
||||
unset GOFLAGS GOOS GOARCH
|
||||
|
||||
mkdir -p "$tmp/headscale/cmd/headscale" "$tmp/headscale/tools"
|
||||
cp "$root/.goreleaser.yml" "$tmp/headscale/"
|
||||
cp "$root/tools/release-check.sh" "$tmp/headscale/tools/"
|
||||
cd "$tmp/headscale"
|
||||
cat > go.mod <<'MOD'
|
||||
module example.com/headscale
|
||||
|
||||
go 1.24.0
|
||||
|
||||
// Tidy removes this block, reproducing release-time go.mod edits.
|
||||
require (
|
||||
)
|
||||
MOD
|
||||
printf 'package main\nfunc main() {}\n' > cmd/headscale/main.go
|
||||
printf 'dist/\nvendor/\n' > .gitignore
|
||||
git init -q
|
||||
git config user.name 'Release check test'
|
||||
git config user.email 'release-check@example.invalid'
|
||||
git remote add origin https://github.com/juanfont/headscale.git
|
||||
git add .
|
||||
git commit -qm 'Create release fixture'
|
||||
git tag v0.0.1
|
||||
check="$PWD/tools/release-check.sh"
|
||||
|
||||
expect_failure() {
|
||||
local label=$1 message=$2
|
||||
shift 2
|
||||
if "$@" > "$tmp/failure.log" 2>&1; then
|
||||
printf 'FAIL: %s unexpectedly succeeded\n' "$label" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -Fq "$message" "$tmp/failure.log"; then
|
||||
cat "$tmp/failure.log" >&2
|
||||
exit 1
|
||||
fi
|
||||
printf 'PASS: %s\n' "$label"
|
||||
}
|
||||
|
||||
# Use the real release hooks and every configured target, without publishing.
|
||||
if ! goreleaser build --snapshot --clean > "$tmp/build.log" 2>&1; then
|
||||
cat "$tmp/build.log" >&2
|
||||
exit 1
|
||||
fi
|
||||
binaries=(dist/headscale_*/headscale)
|
||||
bash "$check" "${binaries[@]}"
|
||||
printf 'PASS: clean release builds, including cross-compiled binaries\n'
|
||||
|
||||
git config status.showUntrackedFiles no
|
||||
printf '// dirty\n' >> cmd/headscale/main.go
|
||||
expect_failure 'unstaged change' 'working tree is dirty' bash "$check"
|
||||
go build -o dist/dirty ./cmd/headscale
|
||||
git add cmd/headscale/main.go
|
||||
expect_failure 'staged change' 'working tree is dirty' bash "$check"
|
||||
git restore --staged --worktree cmd/headscale/main.go
|
||||
expect_failure 'dirty binary after source cleanup' 'lacks clean VCS metadata' bash "$check" dist/dirty
|
||||
|
||||
touch untracked
|
||||
expect_failure 'untracked file despite Git display settings' 'working tree is dirty' bash "$check"
|
||||
rm untracked
|
||||
|
||||
go build -buildvcs=false -o dist/unstamped ./cmd/headscale
|
||||
expect_failure 'missing VCS metadata' 'lacks clean VCS metadata' bash "$check" dist/unstamped
|
||||
expect_failure 'missing binary' 'no such file or directory' bash "$check" dist/missing
|
||||
|
||||
git commit --allow-empty -qm 'Advance fixture HEAD'
|
||||
expect_failure 'binary from another commit' 'was not built from HEAD' bash "$check" "${binaries[0]}"
|
||||
|
||||
# Reintroducing a mutating preparation hook must abort the actual build pipeline.
|
||||
sed -i '/ - go mod vendor/a\ - go mod tidy' .goreleaser.yml
|
||||
git add .goreleaser.yml
|
||||
git commit -qm 'Reproduce release-time tidy'
|
||||
expect_failure 'preparation dirties source' 'working tree is dirty' goreleaser build --snapshot --clean --single-target
|
||||
|
||||
cd "$tmp"
|
||||
expect_failure 'Git failure' 'not a git repository' bash "$check"
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
status=$(git status --porcelain --untracked-files=all)
|
||||
if [[ -n "$status" ]]; then
|
||||
printf 'release: working tree is dirty\n%s\n' "$status" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for binary in "$@"; do
|
||||
info=$(go version -m "$binary")
|
||||
if ! grep -Eq '[[:space:]]vcs.modified=false$' <<< "$info"; then
|
||||
printf 'release: %s lacks clean VCS metadata\n%s\n' "$binary" "$info" >&2
|
||||
exit 1
|
||||
fi
|
||||
revision=$(git rev-parse HEAD)
|
||||
if ! grep -Eq "[[:space:]]vcs.revision=${revision}$" <<< "$info"; then
|
||||
printf 'release: %s was not built from HEAD\n%s\n' "$binary" "$info" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
Reference in new issue
Block a user