Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88f0e24b46 | ||
|
|
603e1e344b | ||
|
|
96e47ab87a | ||
|
|
c3418b3c3b | ||
|
|
5048968cdf |
@@ -1,8 +1,10 @@
|
||||
# Release — Go binaries. Runs on version tags (v1.2.3) pushed to main.
|
||||
# Builds the platform matrix, creates the Gitea release, uploads binaries.
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ["v*.*.*"]
|
||||
tags: ["v*"]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -26,33 +28,31 @@ jobs:
|
||||
- goos: freebsd
|
||||
goarch: riscv64
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: "1.26"
|
||||
|
||||
- name: Download dependencies
|
||||
run: go mod download
|
||||
|
||||
- name: Build
|
||||
- name: Validate tag and build
|
||||
id: build
|
||||
env:
|
||||
REF: ${{ gitea.ref }}
|
||||
|
||||
VERSION: ${{ gitea.ref_name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
VERSION="${REF##*/}"
|
||||
|
||||
if [[ ! "$VERSION" =~ ^v[0-9]+(\.[0-9]+){0,2}([-+].*)?$ ]]; then
|
||||
echo "ERROR: expected a semver tag like v1.2.3, got: '$VERSION' (ref: '$REF')"
|
||||
if ! echo "$VERSION" | grep -qE '^v[0-9]+(\.[0-9]+){0,2}([-+].*)?$'; then
|
||||
echo "ERROR: expected a semver tag like v1.2.3, got: '$VERSION'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VERSION_NO_V="${VERSION#v}"
|
||||
echo "version_no_v=${VERSION_NO_V}" >> "$GITEA_OUTPUT"
|
||||
|
||||
# The tag is the source of truth — inject it into the binary.
|
||||
LDFLAGS="-s -w -X sourcedock.dev/petrbalvin/nuntius/internal/version.Version=${VERSION_NO_V}"
|
||||
mkdir -p bin
|
||||
GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} CGO_ENABLED=0 \
|
||||
@@ -60,6 +60,7 @@ jobs:
|
||||
-o "bin/nuntius-${VERSION_NO_V}-${{ matrix.goos }}-${{ matrix.goarch }}" \
|
||||
./cmd/server
|
||||
|
||||
# Artifacts stay on v3 — v4 detects Gitea as GHES and aborts.
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -67,6 +68,7 @@ jobs:
|
||||
path: bin/nuntius-${{ steps.build.outputs.version_no_v }}-${{ matrix.goos }}-${{ matrix.goarch }}
|
||||
if-no-files-found: error
|
||||
|
||||
# Only binaries matching the runner can be smoke-tested.
|
||||
- name: Smoke test
|
||||
if: matrix.goos == 'linux' && matrix.goarch == 'amd64'
|
||||
run: |
|
||||
@@ -76,8 +78,10 @@ jobs:
|
||||
release:
|
||||
runs-on: fedora
|
||||
needs: build
|
||||
permissions:
|
||||
releases: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
@@ -109,17 +113,12 @@ jobs:
|
||||
- name: Create release
|
||||
env:
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
GITEA_SERVER_URL: ${{ gitea.server_url }}
|
||||
GITEA_REPOSITORY: ${{ gitea.repository }}
|
||||
GITEA_REF_NAME: ${{ gitea.ref_name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# JSON-escape the release body with sed: backslashes first, then
|
||||
# quotes, tabs, and carriage returns, and finally fold newlines into
|
||||
# \n. Wrap the result in quotes to form a JSON string.
|
||||
BODY=$(sed -e 's/\\/\\\\/g' \
|
||||
-e 's/"/\\"/g' \
|
||||
-e 's/\t/\\t/g' \
|
||||
-e 's/\r//g' \
|
||||
release-body.md \
|
||||
| sed ':a;N;$!ba;s/\n/\\n/g')
|
||||
BODY=$(sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/\t/\\t/g' -e 's/\r//g' release-body.md | sed ':a;N;$!ba;s/\n/\\n/g')
|
||||
BODY="\"${BODY}\""
|
||||
|
||||
response=$(curl -sS -w '\n%{http_code}' \
|
||||
@@ -127,31 +126,27 @@ jobs:
|
||||
-H "Content-Type: application/json" \
|
||||
-X POST \
|
||||
"${GITEA_SERVER_URL}/api/v1/repos/${GITEA_REPOSITORY}/releases" \
|
||||
-d "{
|
||||
\"tag_name\": \"${GITEA_REF_NAME}\",
|
||||
\"name\": \"${GITEA_REF_NAME}\",
|
||||
\"body\": ${BODY},
|
||||
\"draft\": false,
|
||||
\"prerelease\": false
|
||||
}")
|
||||
-d "{\"tag_name\":\"${GITEA_REF_NAME}\",\"name\":\"${GITEA_REF_NAME}\",\"body\":${BODY},\"draft\":false,\"prerelease\":false}")
|
||||
|
||||
http_code=$(echo "$response" | tail -1)
|
||||
body=$(echo "$response" | sed '$d')
|
||||
payload=$(echo "$response" | sed '$d')
|
||||
|
||||
echo "HTTP ${http_code}"
|
||||
|
||||
if [ "$http_code" != "201" ]; then
|
||||
echo "Failed to create release: ${body}"
|
||||
echo "Failed to create release: ${payload}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RELEASE_ID=$(echo "$body" | grep -oE '"id"[[:space:]]*:[[:space:]]*[0-9]+' | head -1 | grep -oE '[0-9]+')
|
||||
RELEASE_ID=$(echo "$payload" | grep -oE '"id"[[:space:]]*:[[:space:]]*[0-9]+' | head -1 | grep -oE '[0-9]+')
|
||||
echo "Created release ID=${RELEASE_ID}"
|
||||
printf '%s' "${RELEASE_ID}" > release-id.txt
|
||||
|
||||
- name: Upload assets
|
||||
env:
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
GITEA_SERVER_URL: ${{ gitea.server_url }}
|
||||
GITEA_REPOSITORY: ${{ gitea.repository }}
|
||||
GITEA_REF_NAME: ${{ gitea.ref_name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
RELEASE_ID=$(cat release-id.txt)
|
||||
|
||||
+22
-17
@@ -1,3 +1,4 @@
|
||||
# Test — Go. Runs on push and pull request to development. Never on main.
|
||||
name: Test
|
||||
|
||||
on:
|
||||
@@ -10,9 +11,9 @@ jobs:
|
||||
vet:
|
||||
runs-on: fedora
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: "1.26"
|
||||
|
||||
@@ -20,12 +21,11 @@ jobs:
|
||||
run: go mod download
|
||||
|
||||
- name: gofmt
|
||||
# `gofmt -l` prints the names of unformatted files. An empty
|
||||
# output is the only acceptable result.
|
||||
# gofmt -l prints unformatted files; an empty output is the only pass.
|
||||
run: |
|
||||
unformatted=$(gofmt -l cmd internal pkg)
|
||||
unformatted=$(gofmt -l .)
|
||||
if [ -n "$unformatted" ]; then
|
||||
echo "The following files need gofmt:"
|
||||
echo "These files need gofmt:"
|
||||
echo "$unformatted"
|
||||
exit 1
|
||||
fi
|
||||
@@ -37,36 +37,44 @@ jobs:
|
||||
runs-on: fedora
|
||||
needs: vet
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: "1.26"
|
||||
|
||||
- name: Download dependencies
|
||||
run: go mod download
|
||||
|
||||
- name: Install build tools
|
||||
# The runner images have no gcc; the race detector needs CGO.
|
||||
- name: Install gcc
|
||||
run: dnf install -y gcc
|
||||
|
||||
- name: go test -race
|
||||
run: go test -race -count=1 ./...
|
||||
|
||||
- name: Check coverage threshold
|
||||
# Coverage is measured over the library packages; cmd/ is thin glue.
|
||||
- name: Coverage gate — 80 % minimum
|
||||
run: |
|
||||
set -euo pipefail
|
||||
go test -coverprofile=coverage.out ./internal/... ./pkg/...
|
||||
go tool cover -func=coverage.out | grep '^total:' | python3 -c "import sys; pct=float(sys.stdin.read().split()[2].rstrip('%')); sys.exit(0 if pct >= 80 else 1)" || (echo "ERROR: coverage < 80%"; exit 1)
|
||||
coverage=$(go tool cover -func=coverage.out | awk '/^total:/ { gsub("%", "", $3); print $3 }')
|
||||
echo "Total coverage: ${coverage}%"
|
||||
if awk -v c="$coverage" 'BEGIN { exit !(c+0 < 80) }'; then
|
||||
echo "ERROR: coverage ${coverage}% is below the 80% threshold"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: go test ./examples
|
||||
- name: Build examples
|
||||
run: go build ./examples/...
|
||||
|
||||
build:
|
||||
runs-on: fedora
|
||||
needs: test
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: "1.26"
|
||||
|
||||
@@ -76,8 +84,5 @@ jobs:
|
||||
- name: Build
|
||||
run: go build -ldflags="-s -w" -o bin/nuntius ./cmd/server
|
||||
|
||||
- name: Test
|
||||
run: go test ./...
|
||||
|
||||
- name: Smoke test
|
||||
run: ./bin/nuntius --version
|
||||
|
||||
+4
-10
@@ -7,14 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [development]
|
||||
|
||||
## [1.1.1] — 2026-07-26
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Smoke test restricted to native builds** — cross-compiled binaries
|
||||
(FreeBSD, ARM64, RISC-V, LoongArch) now skip the smoke test step since
|
||||
they cannot execute on the Linux amd64 CI runner.
|
||||
|
||||
## [1.1.0] — 2026-07-26
|
||||
|
||||
### Added
|
||||
@@ -53,9 +45,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
when it finds unformatted files.
|
||||
- **Missing `just fmt` recipe** — added `gofmt -w` target.
|
||||
- **Copyright headers** — added to all Go and Python source files.
|
||||
- **Smoke test restricted to native builds** — cross-compiled binaries now
|
||||
skip the smoke test step since they cannot execute on the Linux amd64 CI
|
||||
runner.
|
||||
|
||||
[development]: https://sourcedock.dev/petrbalvin/nuntius/compare/v1.1.1...development
|
||||
[1.1.1]: https://sourcedock.dev/petrbalvin/nuntius/releases/tag/v1.1.1
|
||||
[development]: https://sourcedock.dev/petrbalvin/nuntius/compare/v1.1.0...development
|
||||
[1.1.0]: https://sourcedock.dev/petrbalvin/nuntius/releases/tag/v1.1.0
|
||||
|
||||
## [1.0.0] — 2026-06-20
|
||||
|
||||
@@ -10,4 +10,4 @@ package version
|
||||
const Name = "nuntius"
|
||||
|
||||
// Version is the nuntius release version. Follows SemVer.
|
||||
var Version = "1.1.1"
|
||||
var Version = "1.1.0"
|
||||
|
||||
Reference in New Issue
Block a user