Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 0 additions & 52 deletions .github/workflows/ci-go-checks.yml

This file was deleted.

136 changes: 136 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
name: ci

on:
pull_request:
push:
branches:
- main

permissions:
contents: read

jobs:
verify:
# Concurrency is scoped to this job so superseded PR pushes cancel their
# own verify runs WITHOUT cancelling an in-flight `release` job that may
# already have created a tag/GitHub Release.
concurrency:
group: verify-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
if: ${{ github.event_name != 'push' || !contains(github.event.head_commit.message, '[skip ci]') }}
name: verify (fmt + lint + test + coverage)
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Read Go version from .tool-versions
id: go-version
shell: bash
run: |
set -euo pipefail
version=$(awk '$1 == "golang" { print $2; exit }' .tool-versions)
if [ -z "${version}" ]; then
echo "Failed to determine Go version from .tool-versions" >&2
exit 1
fi
echo "version=${version}" >> "$GITHUB_OUTPUT"

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ steps.go-version.outputs.version }}
cache: true
cache-dependency-path: |
**/go.sum

- name: Run verifier (fmt + lint + test + coverage gate)
run: go run ./cmd/verify

# Tag, release notes, GitHub Release, binaries, and Homebrew tap update
# all happen here on push to `main` after `verify` passes. Conventional
# Commits drive the version. No manual `scripts/release.sh` step.
release:
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, '[skip ci]') }}
name: release
needs: [verify]
runs-on: ubuntu-latest
timeout-minutes: 20
concurrency:
group: release-${{ github.repository }}-main
cancel-in-progress: false
permissions:
contents: write
issues: write
pull-requests: write
id-token: write
attestations: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: true

- name: Read Go version from .tool-versions
id: go-version
shell: bash
run: |
set -euo pipefail
version=$(awk '$1 == "golang" { print $2; exit }' .tool-versions)
if [ -z "${version}" ]; then
echo "Failed to determine Go version from .tool-versions" >&2
exit 1
fi
echo "version=${version}" >> "$GITHUB_OUTPUT"
Comment thread
cursor[bot] marked this conversation as resolved.

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ steps.go-version.outputs.version }}
cache: true
cache-dependency-path: |
**/go.sum

# Decides next version from Conventional Commits, creates tag + GitHub
# Release with notes. Outputs `new_release_published` and
# `new_release_version` for downstream steps.
- name: Run semantic-release
id: release
uses: cycjimmy/semantic-release-action@v4
with:
extra_plugins: |
conventional-changelog-conventionalcommits@7
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GIT_AUTHOR_NAME: glitch418x
GIT_AUTHOR_EMAIL: 189487110+glitch418x@users.noreply.github.com
GIT_COMMITTER_NAME: glitch418x
GIT_COMMITTER_EMAIL: 189487110+glitch418x@users.noreply.github.com

# semantic-release creates the tag on GitHub via the Release API; pull
# it down so GoReleaser's `git describe`-based template lookups work.
- name: Fetch release tag
if: steps.release.outputs.new_release_published == 'true'
run: git fetch --tags --force

- name: Run GoReleaser
if: steps.release.outputs.new_release_published == 'true'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Allow GoReleaser to run on release-job retries

Run GoReleaser is gated on steps.release.outputs.new_release_published == 'true', so if semantic-release succeeds (tag/release created) but a later step fails, rerunning the job on the same commit will skip artifact publishing because semantic-release now reports no new release. In that failure mode (for example transient GoReleaser/Homebrew token issues), the GitHub release stays published without binaries/checksums unless someone performs a manual recovery.

Useful? React with 👍 / 👎.

uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
version: "~> v2"
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAP_GITHUB_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }}
GORELEASER_CURRENT_TAG: ${{ steps.release.outputs.new_release_git_tag }}

- name: Attest build provenance
if: steps.release.outputs.new_release_published == 'true'
uses: actions/attest-build-provenance@v2
with:
subject-path: "dist/healthd_*.tar.gz"
86 changes: 0 additions & 86 deletions .github/workflows/release.yml

This file was deleted.

2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/bin/
/dist/
75 changes: 75 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
version: 2

project_name: healthd

before:
hooks:
- go mod tidy

builds:
- id: healthd
main: .
binary: healthd
env:
- CGO_ENABLED=0
flags:
- -trimpath
ldflags:
- -s -w
- -X github.com/uinaf/healthd/cmd.Version={{ .Version }}
- -X github.com/uinaf/healthd/cmd.Commit={{ .Commit }}
- -X github.com/uinaf/healthd/cmd.BuildDate={{ .Date }}
goos:
- darwin
goarch:
- arm64
- amd64

archives:
# Match the existing artifact layout: healthd_v0.X.Y_darwin_arm64.tar.gz
# containing only the `healthd` binary. The leading `v` keeps the brew
# formula URL pattern stable across releases.
- id: healthd
name_template: "{{ .ProjectName }}_{{ .Tag }}_{{ .Os }}_{{ .Arch }}"
formats: [tar.gz]
# Match existing artifact layout: a tarball containing only the `healthd`
# binary. `none*` disables the README/LICENSE auto-include.
files:
- none*

checksum:
name_template: "checksums.txt"
algorithm: sha256

snapshot:
version_template: "{{ incpatch .Version }}-snapshot-{{ .ShortCommit }}"

changelog:
# semantic-release owns release notes; goreleaser ships binaries only.
disable: true

release:
github:
owner: uinaf
name: healthd
# semantic-release creates the release first; goreleaser uploads artifacts to it.
mode: append
prerelease: auto

brews:
- name: healthd
repository:
owner: uinaf
name: homebrew-tap
branch: main
token: "{{ .Env.TAP_GITHUB_TOKEN }}"
directory: Formula
commit_author:
name: glitch418x
email: 189487110+glitch418x@users.noreply.github.com
commit_msg_template: "healthd: bump to {{ .Tag }}"
homepage: "https://github.com/uinaf/healthd"
description: "Pluggable local host health-check daemon"
license: "MIT"
test: |
assert_match "healthd", shell_output("#{bin}/healthd --help")
26 changes: 26 additions & 0 deletions .releaserc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"branches": ["main"],
"tagFormat": "v${version}",
"plugins": [
[
"@semantic-release/commit-analyzer",
{
"preset": "conventionalcommits",
"releaseRules": [
{ "type": "docs", "release": false },
{ "type": "chore", "release": false },
{ "type": "test", "release": false },
{ "type": "refactor", "release": "patch" },
{ "type": "perf", "release": "patch" },
{ "type": "build", "release": false },
{ "type": "ci", "release": false }
]
}
],
[
"@semantic-release/release-notes-generator",
{ "preset": "conventionalcommits" }
],
"@semantic-release/github"
]
}
4 changes: 3 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ go run ./cmd/verify # full gate (fmt + lint + test + 80% cov
go build ./... # build
go test ./... # quick: all tests, no gate
go build -o ~/.local/bin/healthd . # install to ~/.local/bin
scripts/release.sh vX.Y.Z # full release + brew update
```

## Releases
Automated on push to `main`. CI verifies, `semantic-release` decides the version from Conventional Commits and tags + drafts the GitHub Release, then GoReleaser builds darwin/arm64 + darwin/amd64 tarballs and updates the formula in `uinaf/homebrew-tap`. No manual script — write `feat:` / `fix:` / `feat!:` commits and the bump happens. Use `[skip ci]` in the message to skip a release for a given push.

## Env
- `HEALTHD_CONFIG` — override config path (also via `--config`); useful for per-worktree isolation

Expand Down
Loading
Loading