7.7 KiB
7.7 KiB
Release Pipeline Design (Plan 4c)
Date: 2026-04-14 Scope: Plan 4c of the Archduino Go rewrite — ship versioned releases and enable one-line install.
Goal
Let a user install Archduino with a single curl | bash, and let the maintainer ship versioned releases with a single make release, hosted entirely on the self-hosted Gitea instance at gitlab.hive-brain.de:2222.
Deliverables
bootstrap.sh— thin curl-piped shim that installs prereqs, downloads the latest release, and execsarchduino install..goreleaser.yaml— cross-compile + archive + checksum + changelog + publish to Gitea Releases.Makefilewithreleaseandsnapshottargets — driven bysvufor SemVer bumps..gitea/workflows/release.yml— tag-triggered workflow that runs goreleaser.
Components
1. bootstrap.sh (repo root)
Replaces the legacy install.sh (which is Bash-era and will be removed/archived).
Behavior:
set -euo pipefailthroughout.- Detect Arch via
/etc/arch-release; exit 1 with clear message otherwise. sudo pacman -Sy --needed --noconfirm sudo git curl ca-certificates.- Detect arch:
uname -m→x86_64→amd64,aarch64→arm64. Unknown arch → exit 1. - Query Gitea API for latest release:
GET https://gitlab.hive-brain.de/api/v1/repos/MDietermann/Archduino/releases/latestExtracttag_name(e.g.v0.1.0) and use it to locate assets. - Download
archduino_<version-without-v>_linux_<arch>.tar.gzandchecksums.txtinto amktemp -d. - Verify SHA256 via
sha256sum --check --ignore-missing checksums.txt; mismatch → exit 1. - Extract tarball.
- Install with sudo:
- Binary →
/usr/local/bin/archduino(0755), overwriting. completions/archduino.bash→/usr/share/bash-completion/completions/archduino.completions/_archduino→/usr/share/zsh/site-functions/_archduino.completions/archduino.fish→/usr/share/fish/vendor_completions.d/archduino.fish.
- Binary →
exec /usr/local/bin/archduino install "$@"so flags pass through (e.g.--halt-on-error).
Usage:
curl -fsSL https://gitlab.hive-brain.de/MDietermann/Archduino/raw/branch/master/bootstrap.sh | bash
2. .goreleaser.yaml (repo root)
project_name: archduinobefore.hooks:regenerate shell completions via the cobracompletionsubcommand:go run ./cmd/archduino completion bash > completions/archduino.bashgo run ./cmd/archduino completion zsh > completions/_archduinogo run ./cmd/archduino completion fish > completions/archduino.fish- Prerequisite: the
completionsubcommand must be registered on the root cobra command. If not already present, add it as part of the implementation.
builds:- One entry,
main: ./cmd/archduino,binary: archduino. env: [CGO_ENABLED=0].goos: [linux],goarch: [amd64, arm64].ldflags: -s -w -X gitlab.hive-brain.de/MDietermann/Archduino/internal/buildinfo.Version={{.Version}} -X ...Commit={{.Commit}} -X ...Date={{.Date}}(add a smallinternal/buildinfopackage to hold these; surface viaarchduino version).
- One entry,
archives:- Format tar.gz.
- Name template
archduino_{{.Version}}_linux_{{.Arch}}. - Files: binary +
completions/*+README.md+LICENSE(add if missing).
checksum: name_template: 'checksums.txt'(SHA256).changelog:use: git- Filters: exclude
^chore:,^docs:,^test:,^ci:,^style:,Merge pull request,Merge branch. - Groups:
Features(^feat),Bug fixes(^fix|^perf),Others(everything else).
release:gitea_urls.api: https://gitlab.hive-brain.de/api/v1gitea_urls.download: https://gitlab.hive-brain.de
3. Makefile (repo root)
Targets:
snapshot—goreleaser release --snapshot --clean. No tagging, no publish. For local build-matrix validation.release— SemVer bump flow:- Assert working tree clean and current branch is
master; abort otherwise. CURRENT=$$(svu current)andNEXT=$$(svu next). Display both plus the commit log sinceCURRENT.- Prompt
Tag $NEXT and push? [y/N]. Abort on anything buty. git tag $$NEXT && git push origin $$NEXT. The actual release is then produced by CI.
- Assert working tree clean and current branch is
completions— regenerate completions intocompletions/locally (useful for dev).build— localgo build ./cmd/archduinofor quick smoke.
svu is a dev dependency; README gains a one-line note: go install github.com/caarlos0/svu@latest.
4. .gitea/workflows/release.yml
- Trigger:
on: push: tags: ['v*']. runs-on: ubuntu-latest(Gitea Actions convention; matches runner labels).- Steps:
actions/checkout@v4withfetch-depth: 0(goreleaser needs full history for changelog).actions/setup-go@v5with the Go version pinned ingo.mod.goreleaser/goreleaser-action@v6withargs: release --clean.
- Env:
GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}. Token is created manually in Gitea UI (repo-scoped,write:package/write:repositoryas needed) and stored as a repo secret before first release. - Prerequisite (documented, not executed by the plan): a Gitea Actions runner must be registered on the instance. One-time setup outside the scope of this spec.
Data flow
dev: git commit -m "feat: ..." (conventional commits)
dev: make release → svu computes vX.Y.Z → git tag + push
Gitea Actions: tag push → goreleaser --clean → Gitea Release published
(tarballs + checksums.txt + changelog)
user: curl … | bash → bootstrap.sh → Gitea API (latest release) → tarball →
sha256 verify → /usr/local/bin + completions → exec archduino install
Versioning
SemVer driven by Conventional Commits via svu:
feat:→ minorfix:/perf:→ patchfeat!:orBREAKING CHANGE:footer → majorchore:/docs:/refactor:/test:/ci:/style:→ no release
First release: v0.1.0 (seed tag so svu has a baseline; manual one-time git tag v0.1.0).
Error handling
bootstrap.sh: checksum mismatch, non-Arch host, arch detection failure, non-200 from API → exit 1 with a specific message;set -euo pipefailcovers the rest.- goreleaser is transactional — the Gitea Release is created after artifacts upload successfully, so a mid-run failure leaves no partial release.
make releaseaborts before tagging if the tree is dirty or not onmaster.
Testing
make snapshotlocally verifies the build matrix and archive contents without publishing.bootstrap.shtested against a snapshot tarball in a throwaway Arch container:docker run --rm -it archlinux bash→ serve the tarball locally → run bootstrap with an overridden base URL (env var hook, e.g.ARCHDUINO_RELEASE_BASE) for test runs.- No Go test changes; this is all out-of-band release machinery.
Out of scope (deferred)
- GPG-signed checksums (revisit if/when distribution widens).
- Debian/Fedora/macOS builds (waiting on multi-distro support elsewhere in the roadmap).
- Homebrew tap and AUR PKGBUILD (AUR is a natural follow-up but tracked separately).
- Automated "release PR" bots (release-please / semantic-release) —
svu+ manualmake releaseis the chosen trigger.
File touch list
New:
bootstrap.sh.goreleaser.yamlMakefile.gitea/workflows/release.ymlinternal/buildinfo/buildinfo.go(tiny — holdsVersion,Commit,Datevars)completions/(gitignored; generated)LICENSE(if missing)
Modified:
cmd/archduino/main.go(register cobracompletionsubcommand if absent; wire aversionsubcommand that printsbuildinfo).README.md(install-via-bootstrap instructions,svunote)..gitignore(adddist/,completions/).
Removed/archived:
install.sh(legacy Bash installer — superseded bybootstrap.sh+ Go binary).