refactor(ci): split release pipeline, add nfpm/homebrew/git-cliff

Split monolithic release.yml into independent workflows:
- release-binaries.yml: tag-triggered, GoReleaser + git-cliff notes
- release-docker.yml: tag-triggered + manual dispatch, SHA tags

Add DEB/RPM packaging via nfpm in GoReleaser. Add Homebrew cask
config (skip_upload until macOS builds exist). Replace GoReleaser
built-in changelog with git-cliff for structured release notes.
This commit is contained in:
2026-06-01 21:14:54 -04:00
parent a08d6ce2c5
commit 50eb43971c
5 changed files with 161 additions and 60 deletions
+53
View File
@@ -0,0 +1,53 @@
name: Release Binaries
on:
push:
tags:
- "[0-9]*"
jobs:
release:
runs-on: ubuntu-latest
defaults:
run:
shell: sh
steps:
- name: Install build tools
run: apk add --no-cache git gcc musl-dev
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-go@v5
with:
go-version: "1.26"
- uses: actions/cache@v4
with:
path: |
~/go/pkg/mod
~/.cache/go-build
key: release-go-${{ hashFiles('go.sum') }}
restore-keys: release-go-
- name: Install git-cliff
run: |
apk add --no-cache curl
curl -sSL https://github.com/orhun/git-cliff/releases/latest/download/git-cliff-x86_64-unknown-linux-musl.tar.gz | tar xz
mv git-cliff-*/git-cliff /usr/local/bin/
git-cliff --version
- name: Generate release notes
run: git-cliff --current --strip header -o /tmp/release-notes.md
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v7
with:
distribution: goreleaser
version: "~> v2"
args: release --clean --release-notes=/tmp/release-notes.md
env:
GORELEASER_FORCE_TOKEN: gitea
GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}
GITEA_API_URL: http://gitea:3000/api/v1
@@ -1,53 +1,36 @@
name: Release
name: Release Docker
on:
push:
tags:
- "[0-9]*"
workflow_dispatch:
inputs:
tag:
description: "Image tag (e.g. 2026.06.1). Defaults to latest commit SHA."
required: false
jobs:
release:
runs-on: ubuntu-latest
defaults:
run:
shell: sh
steps:
- name: Install build tools
run: apk add --no-cache git gcc musl-dev
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-go@v5
with:
go-version: "1.26"
- uses: actions/cache@v4
with:
path: |
~/go/pkg/mod
~/.cache/go-build
key: release-go-${{ hashFiles('go.sum') }}
restore-keys: release-go-
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v7
with:
distribution: goreleaser
version: "~> v2"
args: release --clean
env:
GORELEASER_FORCE_TOKEN: gitea
GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}
GITEA_API_URL: http://gitea:3000/api/v1
docker:
runs-on: docker-builder
needs: [release]
steps:
- uses: actions/checkout@v4
- name: Resolve image tag
id: meta
run: |
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7)
echo "short_sha=$SHORT_SHA" >> "$GITHUB_OUTPUT"
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
TAG="${{ github.event.inputs.tag }}"
if [ -z "$TAG" ]; then
TAG="${{ github.sha }}"
fi
else
TAG="${{ github.ref_name }}"
fi
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
@@ -69,10 +52,11 @@ jobs:
sbom: true
provenance: mode=max
tags: |
lerkolabs/uptop:${{ github.ref_name }}
lerkolabs/uptop:${{ steps.meta.outputs.tag }}
lerkolabs/uptop:latest
lerkolabs/uptop:sha-${{ steps.meta.outputs.short_sha }}
build-args: |
VERSION=${{ github.ref_name }}
VERSION=${{ steps.meta.outputs.tag }}
COMMIT=${{ github.sha }}
BUILD_DATE=${{ github.event.head_commit.timestamp }}
+2 -14
View File
@@ -1,10 +1,3 @@
# Created by https://www.toptal.com/developers/gitignore/api/go
# Edit at https://www.toptal.com/developers/gitignore?templates=go
### Go ###
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
@@ -24,16 +17,11 @@
# Go workspace file
go.work
# End of https://www.toptal.com/developers/gitignore/api/go
/uptop
/dist
uptop.db*
.ssh
authorized_keys
tmp
*.local.json
*.local.md
*.local.md
+37 -6
View File
@@ -33,10 +33,41 @@ archives:
checksum:
name_template: checksums.txt
nfpms:
- package_name: uptop
file_name_template: "{{ .ConventionalFileName }}"
vendor: LerkoLabs
homepage: https://gitea.lerkolabs.com/lerkolabs/uptop
maintainer: Tyler Koenig <tyler@lerkolabs.com>
description: Self-hosted uptime monitoring with a TUI over SSH
license: MIT
section: net
priority: optional
formats:
- deb
- rpm
bindir: /usr/bin
contents:
- src: ./LICENSE
dst: /usr/share/doc/uptop/LICENSE
type: doc
homebrew_casks:
- name: uptop
homepage: https://gitea.lerkolabs.com/lerkolabs/uptop
description: Self-hosted uptime monitoring with a TUI over SSH
directory: Casks
skip_upload: true
commit_msg_template: "update uptop to {{ .Tag }}"
url:
template: "https://gitea.lerkolabs.com/lerkolabs/uptop/releases/download/{{ .Tag }}/{{ .ArtifactName }}"
repository:
owner: lerkolabs
name: homebrew-tap
git:
url: "ssh://git@gitea.lerkolabs.com:2222/lerkolabs/homebrew-tap.git"
private_key: "{{ if index .Env \"TAP_SSH_KEY\" }}{{ .Env.TAP_SSH_KEY }}{{ end }}"
ssh_command: "ssh -o StrictHostKeyChecking=accept-new"
changelog:
sort: asc
filters:
exclude:
- "^docs:"
- "^chore:"
- "^style:"
disable: true
+45
View File
@@ -0,0 +1,45 @@
[changelog]
header = """
# Changelog\n
"""
body = """
{% if version %}\
## [{{ version }}] — {{ timestamp | date(format="%Y-%m-%d") }}
{% else %}\
## [Unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | striptags | trim }}
{% for commit in commits %}
- {{ commit.message | split(pat="\n") | first | trim }}\
{% endfor %}
{% endfor %}\n
"""
trim = true
[git]
conventional_commits = true
filter_unconventional = true
split_commits = false
protect_breaking_commits = false
filter_commits = false
tag_pattern = "[0-9]*"
topo_order = false
sort_commits = "oldest"
commit_parsers = [
{ message = "^feat", group = "Added" },
{ message = "^fix", group = "Fixed" },
{ message = "^perf", group = "Changed" },
{ message = "^refactor", group = "Changed" },
{ message = "^security", group = "Security" },
{ body = ".*security", group = "Security" },
{ body = "BREAKING", group = "Breaking" },
{ footer = "BREAKING.CHANGE", group = "Breaking" },
{ message = "^docs", skip = true },
{ message = "^style", skip = true },
{ message = "^chore", skip = true },
{ message = "^ci", skip = true },
{ message = "^test", skip = true },
{ message = "^build", skip = true },
]