chore(release): prepare v2.0 infrastructure (Makefile, release.sh, Gitea release workflow, installers, modern versioning)
This commit is contained in:
parent
07586a8fc0
commit
dd34a5b21c
96
.gitea/workflows/release.yml
Normal file
96
.gitea/workflows/release.yml
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
name: Create Release
|
||||||
|
runs-on: ubuntu-gitea
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.24'
|
||||||
|
|
||||||
|
- name: Build for multiple platforms
|
||||||
|
run: |
|
||||||
|
VERSION=${GITHUB_REF#refs/tags/}
|
||||||
|
COMMIT=$(git rev-parse --short HEAD)
|
||||||
|
DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||||
|
mkdir -p build
|
||||||
|
for plat in 'linux/amd64' 'linux/arm64' 'darwin/amd64' 'darwin/arm64' 'windows/amd64'; do
|
||||||
|
IFS='/' read -r OS ARCH <<< "$plat"
|
||||||
|
BIN="gostations-${OS}-${ARCH}"
|
||||||
|
if [ "$OS" = "windows" ]; then BIN="${BIN}.exe"; fi
|
||||||
|
GOOS="$OS" GOARCH="$ARCH" go build -trimpath -ldflags "-s -w \
|
||||||
|
-X 'github.com/gmgauthier/gostations/internal/version.Version=${VERSION}' \
|
||||||
|
-X 'github.com/gmgauthier/gostations/internal/version.Commit=${COMMIT}' \
|
||||||
|
-X 'github.com/gmgauthier/gostations/internal/version.BuildDate=${DATE}' \
|
||||||
|
-X 'main.version=${VERSION}'" -o "build/${BIN}" .
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Prepare assets
|
||||||
|
run: |
|
||||||
|
VERSION=${GITHUB_REF#refs/tags/}
|
||||||
|
for bin in build/gostations-* ; do
|
||||||
|
if [ ! -f "$bin" ]; then continue; fi
|
||||||
|
OSARCH=$(basename "$bin" | sed 's/gostations-//' | sed 's/\.exe$//')
|
||||||
|
tar czf "build/gostations-${OSARCH}-${VERSION}.tar.gz" -C build "$(basename "$bin")"
|
||||||
|
done
|
||||||
|
sha256sum build/gostations-*.tar.gz | tee build/checksums.txt
|
||||||
|
|
||||||
|
# Include useful scripts from repo (if present)
|
||||||
|
[ -f scripts/gostations-install.sh ] && cp scripts/gostations-install.sh build/
|
||||||
|
[ -f scripts/gostations-install.ps1 ] && cp scripts/gostations-install.ps1 build/
|
||||||
|
|
||||||
|
# Clean raw binaries (we ship the tarballs)
|
||||||
|
for plat in 'linux/amd64' 'linux/arm64' 'darwin/amd64' 'darwin/arm64' 'windows/amd64'; do
|
||||||
|
IFS='/' read -r OS ARCH <<< "$plat"
|
||||||
|
BIN="gostations-${OS}-${ARCH}"
|
||||||
|
if [ "$OS" = "windows" ]; then BIN="${BIN}.exe"; fi
|
||||||
|
rm -f "build/${BIN}"
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: apt update && apt install -y jq
|
||||||
|
|
||||||
|
- name: Create Release & Upload Assets
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
run: |
|
||||||
|
VERSION=${GITHUB_REF#refs/tags/}
|
||||||
|
GITEA_API=https://repos.gmgauthier.com/api/v1
|
||||||
|
REPO=${GITHUB_REPOSITORY}
|
||||||
|
|
||||||
|
curl -X POST "${GITEA_API}/repos/${REPO}/releases" \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{
|
||||||
|
\"tag_name\": \"${VERSION}\",
|
||||||
|
\"name\": \"gostations ${VERSION}\",
|
||||||
|
\"body\": \"## Quick Install\n\n### Bash (Linux/macOS)\n\n\`\`\`bash\ncurl -L https://repos.gmgauthier.com/gmgauthier/gostations/releases/download/${VERSION}/gostations-install.sh | VERSION=${VERSION} bash\n\`\`\`\n\n### PowerShell (Windows/macOS/Linux)\n\n\`\`\`powershell\nirm https://repos.gmgauthier.com/gmgauthier/gostations/releases/download/${VERSION}/gostations-install.ps1 | iex\n\`\`\`\n\nPlatform binaries (tar.gz) + checksums.txt are attached. See README.md and CHANGELOG (if present) for details. Legacy wmenu UI still available with --legacy.\"
|
||||||
|
}" > release.json
|
||||||
|
|
||||||
|
RELEASE_ID=$(jq .id release.json)
|
||||||
|
|
||||||
|
for asset in build/* ; do
|
||||||
|
name=$(basename "$asset")
|
||||||
|
mime="application/octet-stream"
|
||||||
|
[[ "$name" =~ \.tar\.gz$ ]] && mime="application/gzip"
|
||||||
|
[[ "$name" =~ \.(txt|sh|ps1)$ ]] && mime="text/plain"
|
||||||
|
curl -X POST "${GITEA_API}/repos/${REPO}/releases/${RELEASE_ID}/assets?name=${name}" \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
|
-H "Content-Type: ${mime}" \
|
||||||
|
--data-binary "@$asset"
|
||||||
|
done
|
||||||
38
CHANGELOG.md
Normal file
38
CHANGELOG.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to gostations will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [2.0.0] - 2026-06-XX
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Full modern TUI (Bubble Tea + bubbles/list + lipgloss) as the **default** experience.
|
||||||
|
- Two-stage UI: station selection list → dedicated playback view.
|
||||||
|
- Playback view inspired by classic Winamp:
|
||||||
|
- Metadata viewer area showing live streamed song titles (via mpv IPC).
|
||||||
|
- Control buttons / keys: skip back/forward, volume (UP/DOWN arrows + on-screen vertical bar), mute toggle, play/pause, stop (returns to list).
|
||||||
|
- mpv JSON IPC player implementation (background playback, no terminal takeover, responsive controls and metadata observation).
|
||||||
|
- Favorites (★) support:
|
||||||
|
- TUI hotkey `f` to toggle.
|
||||||
|
- CLI: `gostations fav list|add|del [index|search|url]`.
|
||||||
|
- Initial view shows your Favorites if any (with ★ markers).
|
||||||
|
- Server-side search: while the filter is active, pressing ENTER performs a fresh lookup and replaces the list.
|
||||||
|
- `--legacy` flag to force the old wmenu UI (preserved for now).
|
||||||
|
- All previous CLI subcommands (`find`, `play`, `fav ...`) continue to work for scripting.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Default UI is now the new TUI (no more wmenu unless --legacy).
|
||||||
|
- Player abstraction extended for controls and metadata.
|
||||||
|
- Build/release process modernized (Makefile, cross-compilation, Gitea release workflow + installers) to match other projects.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Various legacy subExecute / player execution issues from the old architecture.
|
||||||
|
- Test coverage for new TUI playback and player features.
|
||||||
|
|
||||||
|
See the git history for the full list of changes leading to 2.0.
|
||||||
|
|
||||||
|
## [0.2] - Previous
|
||||||
|
|
||||||
|
Legacy wmenu-based UI + initial internal refactoring.
|
||||||
88
Makefile
Normal file
88
Makefile
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
.PHONY: test test-short test-cover lint build install clean help cross release-notes
|
||||||
|
|
||||||
|
# Versioning (override on command line or via env for releases)
|
||||||
|
VERSION ?= dev-$(shell git describe --tags --always --dirty 2>/dev/null || echo unknown)
|
||||||
|
COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
|
||||||
|
DATE ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || echo unknown)
|
||||||
|
|
||||||
|
MODULE = github.com/gmgauthier/gostations
|
||||||
|
LDFLAGS = -s -w \
|
||||||
|
-X '$(MODULE)/internal/version.Version=$(VERSION)' \
|
||||||
|
-X '$(MODULE)/internal/version.Commit=$(COMMIT)' \
|
||||||
|
-X '$(MODULE)/internal/version.BuildDate=$(DATE)' \
|
||||||
|
-X 'main.version=$(VERSION)'
|
||||||
|
|
||||||
|
test:
|
||||||
|
go test ./... -v -race
|
||||||
|
|
||||||
|
test-short:
|
||||||
|
go test -short ./... -v -race
|
||||||
|
|
||||||
|
test-cover:
|
||||||
|
@mkdir -p build
|
||||||
|
go test ./... -coverprofile=build/coverage.out
|
||||||
|
go tool cover -html=build/coverage.out -o build/coverage.html
|
||||||
|
@echo "✅ Coverage report: open build/coverage.html in your browser"
|
||||||
|
|
||||||
|
lint:
|
||||||
|
@which golangci-lint > /dev/null || (echo "❌ golangci-lint not found. Install with:" && echo " go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest" && exit 1)
|
||||||
|
golangci-lint run
|
||||||
|
|
||||||
|
build:
|
||||||
|
@mkdir -p build
|
||||||
|
go build -trimpath -ldflags "$(LDFLAGS)" -o build/gostations .
|
||||||
|
@echo "✅ Dev build: VERSION=$(VERSION) COMMIT=$(COMMIT) DATE=$(DATE)"
|
||||||
|
@build/gostations -v || true
|
||||||
|
|
||||||
|
install: build
|
||||||
|
mkdir -p ~/.local/bin
|
||||||
|
cp build/gostations ~/.local/bin/gostations
|
||||||
|
chmod +x ~/.local/bin/gostations
|
||||||
|
@echo "✅ gostations installed to ~/.local/bin/gostations"
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf build/
|
||||||
|
|
||||||
|
# Cross compile (used by release workflow)
|
||||||
|
cross:
|
||||||
|
@mkdir -p build
|
||||||
|
@for plat in 'linux/amd64' 'linux/arm64' 'darwin/amd64' 'darwin/arm64' 'windows/amd64'; do \
|
||||||
|
IFS='/' read -r OS ARCH <<< "$$plat"; \
|
||||||
|
BIN="gostations-$$OS-$$ARCH"; \
|
||||||
|
if [ "$$OS" = "windows" ]; then BIN="$$BIN.exe"; fi; \
|
||||||
|
echo "Building $$BIN..."; \
|
||||||
|
GOOS=$$OS GOARCH=$$ARCH go build -trimpath -ldflags "$(LDFLAGS)" -o "build/$$BIN" . ; \
|
||||||
|
done
|
||||||
|
@echo "✅ Cross builds complete in build/"
|
||||||
|
|
||||||
|
# Helper to print release notes body (used by release process)
|
||||||
|
release-notes:
|
||||||
|
@echo "## Installation"
|
||||||
|
@echo ""
|
||||||
|
@echo "Download the appropriate archive for your platform from the release assets."
|
||||||
|
@echo ""
|
||||||
|
@echo "### Quick install (Linux/macOS)"
|
||||||
|
@echo ""
|
||||||
|
@echo '```bash'
|
||||||
|
@echo 'curl -L https://repos.gmgauthier.com/gmgauthier/gostations/releases/download/$(VERSION)/gostations-install.sh | VERSION=$(VERSION) bash'
|
||||||
|
@echo '```'
|
||||||
|
@echo ""
|
||||||
|
@echo "### Quick install (Windows / PowerShell)"
|
||||||
|
@echo ""
|
||||||
|
@echo '```powershell'
|
||||||
|
@echo 'irm https://repos.gmgauthier.com/gmgauthier/gostations/releases/download/$(VERSION)/gostations-install.ps1 | iex'
|
||||||
|
@echo '```'
|
||||||
|
@echo ""
|
||||||
|
@echo "See README.md for full details and configuration (radiostations.ini)."
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "Available targets:"
|
||||||
|
@echo " test Run all tests (with race)"
|
||||||
|
@echo " test-short Run tests with -short (skips live integration)"
|
||||||
|
@echo " test-cover Tests + HTML coverage report"
|
||||||
|
@echo " lint Run golangci-lint"
|
||||||
|
@echo " build Optimized dev build (uses git describe for VERSION)"
|
||||||
|
@echo " install Build + install to ~/.local/bin/gostations"
|
||||||
|
@echo " cross Build all release platforms into build/"
|
||||||
|
@echo " release-notes Print suggested Gitea release body text"
|
||||||
|
@echo " clean Remove build/"
|
||||||
18
build.ps1
18
build.ps1
@ -1,17 +1,7 @@
|
|||||||
|
|
||||||
# NOTE: The following commands assumes you have Git For Windows
|
# Modernized. Prefer `make build` / `make install` (via Git Bash or WSL recommended).
|
||||||
# installed, which comes with a bunch of GNU tools packaged for windows:
|
# This remains for basic compatibility.
|
||||||
Set-Variable -Name GIT_COMMIT -Value "$(git rev-list -1 HEAD)"
|
|
||||||
Set-Variable -Name CANONICAL_VERSION -Value "$(cat.exe ./VERSION)-$(uname)"
|
|
||||||
Set-Variable -Name VERSION_STRING -Value "$CANONICAL_VERSION-$GIT_COMMIT"
|
|
||||||
|
|
||||||
Set-Variable -Name buildpath -Value "build/$(uname)/gostations.exe"
|
make build
|
||||||
|
make install
|
||||||
go mod tidy
|
|
||||||
|
|
||||||
go build -o "$buildpath" -ldflags "-X main.version=$VERSION_STRING"
|
|
||||||
|
|
||||||
& $buildpath -v
|
|
||||||
|
|
||||||
Copy-Item $buildpath $HOME/.local/bin -Force
|
|
||||||
|
|
||||||
|
|||||||
20
build.sh
20
build.sh
@ -1,18 +1,8 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
# Modernized build script. Prefer `make build` or `make install`.
|
||||||
|
# This script remains for compatibility.
|
||||||
|
|
||||||
GIT_COMMIT=$(git rev-list -1 HEAD)
|
set -e
|
||||||
export GIT_COMMIT
|
|
||||||
CANONICAL_VERSION=$(cat ./VERSION)-$(uname)
|
|
||||||
export CANONICAL_VERSION
|
|
||||||
VERSION_STRING="$CANONICAL_VERSION-$GIT_COMMIT"
|
|
||||||
export VERSION_STRING
|
|
||||||
|
|
||||||
buildpath="build/$(uname)/gostations"
|
make build
|
||||||
|
make install
|
||||||
go mod tidy
|
|
||||||
|
|
||||||
go build -o "$buildpath" -ldflags "-X main.version=$VERSION_STRING"
|
|
||||||
|
|
||||||
"$buildpath" -v
|
|
||||||
|
|
||||||
cp "$buildpath" ~/.local/bin
|
|
||||||
|
|||||||
18
ci-build.sh
18
ci-build.sh
@ -1,19 +1,7 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
# CI build (old runner compatibility). Uses Makefile for consistency.
|
||||||
|
|
||||||
mkdir -p build
|
set -e
|
||||||
|
|
||||||
GIT_COMMIT=$(git rev-list -1 HEAD)
|
make build
|
||||||
export GIT_COMMIT
|
|
||||||
CANONICAL_VERSION=$(cat ./VERSION)-$(uname)
|
|
||||||
export CANONICAL_VERSION
|
|
||||||
VERSION_STRING="$CANONICAL_VERSION-$GIT_COMMIT"
|
|
||||||
export VERSION_STRING
|
|
||||||
|
|
||||||
buildpath="build/$(uname)/gostations"
|
|
||||||
|
|
||||||
/usr/local/go/bin/go mod tidy
|
|
||||||
|
|
||||||
/usr/local/go/bin/go build -o "$buildpath" -ldflags "-X main.version=$VERSION_STRING"
|
|
||||||
|
|
||||||
"$buildpath" -v
|
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package version
|
package version
|
||||||
|
|
||||||
// These vars are set at build time via -ldflags, e.g.
|
// These vars are set at build time via -ldflags (see Makefile and .gitea/workflows/release.yml), e.g.
|
||||||
// -ldflags "-X github.com/gmgauthier/gostations/internal/version.Version=0.3 -X .../Commit=$(git rev-list -1 HEAD)"
|
// -ldflags "-X github.com/gmgauthier/gostations/internal/version.Version=2.0.0 -X .../Commit=... -X .../BuildDate=..."
|
||||||
var (
|
var (
|
||||||
Version = "dev"
|
Version = "dev"
|
||||||
Commit = ""
|
Commit = ""
|
||||||
|
|||||||
95
release.sh
Executable file
95
release.sh
Executable file
@ -0,0 +1,95 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# release.sh — One-command release driver for gostations (modeled on grokkit)
|
||||||
|
# Usage: ./release.sh v2.0.0
|
||||||
|
#
|
||||||
|
# This will:
|
||||||
|
# - Create the git tag (so downstream CI/release can see it)
|
||||||
|
# - Help generate/update CHANGELOG (via grokkit if available)
|
||||||
|
# - Commit the changes
|
||||||
|
# - Push tag + commit
|
||||||
|
# - Print suggested Gitea release notes body
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
VERSION="${1:-}"
|
||||||
|
|
||||||
|
if [[ -z "$VERSION" || ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)? ]]; then
|
||||||
|
echo "❌ Usage: $0 vX.Y.Z"
|
||||||
|
echo " Example: $0 v2.0.0"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "🚀 Starting release process for gostations $VERSION..."
|
||||||
|
|
||||||
|
# Safety check: clean working tree
|
||||||
|
if [[ -n $(git status --porcelain) ]]; then
|
||||||
|
echo "❌ Working tree is dirty. Commit or stash changes first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Final human confirmation
|
||||||
|
echo ""
|
||||||
|
echo "This will:"
|
||||||
|
echo " 1. Create git tag $VERSION"
|
||||||
|
echo " 2. (If grokkit available) Run grokkit changelog + commit for CHANGELOG.md"
|
||||||
|
echo " 3. Push the commit + tag"
|
||||||
|
echo " 4. Print ready-to-paste text for the Gitea release page"
|
||||||
|
echo ""
|
||||||
|
read -p "Proceed with release $VERSION? (y/N) " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Aborted."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 1. Create the tag early (CI release workflow triggers on tag)
|
||||||
|
echo "🏷️ Creating tag $VERSION..."
|
||||||
|
git tag "$VERSION"
|
||||||
|
|
||||||
|
# 2. Changelog / release prep (best effort using grokkit if present on PATH)
|
||||||
|
if command -v grokkit >/dev/null 2>&1; then
|
||||||
|
echo "📝 Generating/updating CHANGELOG.md via grokkit..."
|
||||||
|
grokkit changelog --version "$VERSION" || echo "⚠️ grokkit changelog returned non-zero (continuing)"
|
||||||
|
|
||||||
|
if [[ -n $(git status --porcelain -- CHANGELOG.md) ]]; then
|
||||||
|
echo "📦 Committing changelog changes via grokkit..."
|
||||||
|
git add CHANGELOG.md
|
||||||
|
grokkit commit || echo "⚠️ grokkit commit may need manual follow-up"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "ℹ️ grokkit not found on PATH. Skipping automated changelog."
|
||||||
|
echo " You can manually edit CHANGELOG.md before the next steps if desired."
|
||||||
|
echo " Then run: git add CHANGELOG.md && git commit -m 'chore(release): $VERSION'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3. Push (tag was created earlier; push any new commit + tags)
|
||||||
|
echo "📤 Pushing commit (if any) + tag..."
|
||||||
|
git push || true
|
||||||
|
git push --tags
|
||||||
|
|
||||||
|
# 4. Print nice release notes for Gitea
|
||||||
|
echo ""
|
||||||
|
echo "✅ Release $VERSION pushed!"
|
||||||
|
echo ""
|
||||||
|
echo "📋 Copy-paste the following into the Gitea release notes body:"
|
||||||
|
echo "------------------------------------------------------------"
|
||||||
|
make -s release-notes VERSION="$VERSION" || cat <<EOF
|
||||||
|
## gostations ${VERSION}
|
||||||
|
|
||||||
|
New major release: full modern TUI (Bubble Tea) is now the default.
|
||||||
|
|
||||||
|
- Two-stage UI: station browser → dedicated playback view (Winamp-inspired)
|
||||||
|
- Live stream metadata display
|
||||||
|
- Playback controls: skip, volume (↑/↓ + vertical bar), mute, play/pause, stop (returns to list)
|
||||||
|
- mpv JSON IPC for responsive controls + metadata (no terminal takeover)
|
||||||
|
- Favorites (★) management in both TUI and CLI (fav list/add/del [index])
|
||||||
|
- Server-side search on ENTER while filtering
|
||||||
|
- Legacy wmenu UI still available via --legacy (for now)
|
||||||
|
- All previous CLI subcommands (find, play, fav) preserved
|
||||||
|
|
||||||
|
See the commit history and updated README for details.
|
||||||
|
EOF
|
||||||
|
echo "------------------------------------------------------------"
|
||||||
|
echo ""
|
||||||
|
echo "🎉 Now go to Gitea and create the release using the tag $VERSION."
|
||||||
|
echo " The workflow will automatically build cross-platform assets and attach them."
|
||||||
49
scripts/gostations-install.ps1
Normal file
49
scripts/gostations-install.ps1
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
param(
|
||||||
|
[string]$Version = $env:VERSION
|
||||||
|
)
|
||||||
|
|
||||||
|
if (-not $Version) {
|
||||||
|
Write-Error "Provide -Version or set VERSION env var, e.g. VERSION=2.0.0"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$Version = $Version.TrimStart('v')
|
||||||
|
|
||||||
|
$GITEA_BASE = "https://repos.gmgauthier.com/gmgauthier/gostations"
|
||||||
|
|
||||||
|
$OS = if ($IsWindows) { "windows" } elseif ($IsMacOS) { "darwin" } else { "linux" }
|
||||||
|
$ARCH = if ([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture -eq "X64") { "amd64" } else { "arm64" }
|
||||||
|
|
||||||
|
$ASSET = "gostations-$OS-$ARCH-v$Version.tar.gz"
|
||||||
|
|
||||||
|
Write-Host "Installing gostations $Version for $OS/$ARCH..."
|
||||||
|
|
||||||
|
$tempDir = New-TemporaryFile | % { rm $_; mkdir $_ }
|
||||||
|
try {
|
||||||
|
Push-Location $tempDir
|
||||||
|
|
||||||
|
Write-Host "Downloading $ASSET..."
|
||||||
|
Invoke-WebRequest -Uri "$GITEA_BASE/releases/download/v$Version/$ASSET" -OutFile "asset.tar.gz"
|
||||||
|
|
||||||
|
Write-Host "Downloading checksums.txt..."
|
||||||
|
Invoke-WebRequest -Uri "$GITEA_BASE/releases/download/v$Version/checksums.txt" -OutFile "checksums.txt"
|
||||||
|
|
||||||
|
# Extract (tar on Windows via tar if available, or 7z, but assume tar in modern PS)
|
||||||
|
Write-Host "Extracting..."
|
||||||
|
tar -xzf asset.tar.gz
|
||||||
|
|
||||||
|
$binary = "gostations-$OS-$ARCH"
|
||||||
|
if ($OS -eq "windows") { $binary += ".exe" }
|
||||||
|
|
||||||
|
$installDir = "$HOME\.local\bin"
|
||||||
|
New-Item -ItemType Directory -Force -Path $installDir | Out-Null
|
||||||
|
|
||||||
|
Move-Item -Force $binary "$installDir\gostations.exe" -ErrorAction SilentlyContinue
|
||||||
|
Move-Item -Force $binary "$installDir\gostations" -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
Write-Host "✅ gostations $Version installed to $installDir\gostations"
|
||||||
|
& "$installDir\gostations" -v
|
||||||
|
} finally {
|
||||||
|
Pop-Location
|
||||||
|
Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
78
scripts/gostations-install.sh
Executable file
78
scripts/gostations-install.sh
Executable file
@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
VERSION=${VERSION:-${1:?Provide VERSION env or arg, e.g. VERSION=2.0.0 bash gostations-install.sh}}
|
||||||
|
|
||||||
|
# Strip leading 'v' if present
|
||||||
|
VERSION=${VERSION#v}
|
||||||
|
|
||||||
|
GITEA_BASE=https://repos.gmgauthier.com/gmgauthier/gostations
|
||||||
|
|
||||||
|
# Platform detection
|
||||||
|
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||||
|
case "$OS" in
|
||||||
|
linux) OS=linux ;;
|
||||||
|
darwin) OS=darwin ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
ARCH=$(uname -m)
|
||||||
|
case "$ARCH" in
|
||||||
|
x86_64|amd64) ARCH=amd64 ;;
|
||||||
|
arm64|aarch64) ARCH=arm64 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
ASSET="gostations-${OS}-${ARCH}-v${VERSION}.tar.gz"
|
||||||
|
|
||||||
|
echo "Installing gostations ${VERSION} for ${OS}/${ARCH}..."
|
||||||
|
|
||||||
|
TEMP_DIR=$(mktemp -d)
|
||||||
|
trap 'rm -rf "${TEMP_DIR}"' EXIT
|
||||||
|
|
||||||
|
cd "${TEMP_DIR}"
|
||||||
|
|
||||||
|
# Download asset + checksums
|
||||||
|
echo "Downloading ${ASSET}..."
|
||||||
|
curl -fL "${GITEA_BASE}/releases/download/v${VERSION}/${ASSET}" -o asset.tar.gz
|
||||||
|
|
||||||
|
echo "Downloading checksums.txt..."
|
||||||
|
curl -fL "${GITEA_BASE}/releases/download/v${VERSION}/checksums.txt" -o checksums.txt
|
||||||
|
|
||||||
|
# Robust checksum verification
|
||||||
|
echo "Verifying checksum..."
|
||||||
|
CHECKSUM_CMD=""
|
||||||
|
if command -v sha256sum >/dev/null 2>&1; then
|
||||||
|
CHECKSUM_CMD="sha256sum"
|
||||||
|
elif command -v shasum >/dev/null 2>&1; then
|
||||||
|
CHECKSUM_CMD="shasum -a 256"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$CHECKSUM_CMD" ] && [ -f checksums.txt ]; then
|
||||||
|
HASH=$(grep -oE '[0-9a-f]{64}\s+build/[^ ]*' checksums.txt | grep "${ASSET}" | cut -d' ' -f1 || true)
|
||||||
|
if [ -z "$HASH" ]; then
|
||||||
|
echo "⚠️ No checksum entry found for ${ASSET} – continuing without verification"
|
||||||
|
else
|
||||||
|
echo "${HASH} asset.tar.gz" | $CHECKSUM_CMD --check - || {
|
||||||
|
echo "❌ Checksum mismatch for ${ASSET}!"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
echo "✅ Checksum verified successfully"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "⚠️ Checksum tool not found (sha256sum/shasum) – skipping verification"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract
|
||||||
|
echo "Extracting asset..."
|
||||||
|
tar xzf asset.tar.gz
|
||||||
|
BINARY="gostations-${OS}-${ARCH}"
|
||||||
|
if [ "$OS" = "windows" ]; then BINARY="${BINARY}.exe"; fi
|
||||||
|
|
||||||
|
# Install
|
||||||
|
INSTALL_DIR="${HOME}/.local/bin"
|
||||||
|
mkdir -p "${INSTALL_DIR}"
|
||||||
|
mv "${BINARY}" "${INSTALL_DIR}/gostations" 2>/dev/null || mv "${BINARY}" "${INSTALL_DIR}/gostations.exe" 2>/dev/null || true
|
||||||
|
chmod +x "${INSTALL_DIR}/gostations" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "✅ gostations ${VERSION} installed to ${INSTALL_DIR}/gostations"
|
||||||
|
echo "Add to PATH if needed: export PATH=\"${INSTALL_DIR}:\$PATH\""
|
||||||
|
gostations -v || true
|
||||||
@ -14,11 +14,18 @@ import (
|
|||||||
playerpkg "github.com/gmgauthier/gostations/internal/player"
|
playerpkg "github.com/gmgauthier/gostations/internal/player"
|
||||||
"github.com/gmgauthier/gostations/internal/radio"
|
"github.com/gmgauthier/gostations/internal/radio"
|
||||||
"github.com/gmgauthier/gostations/internal/ui"
|
"github.com/gmgauthier/gostations/internal/ui"
|
||||||
|
ver "github.com/gmgauthier/gostations/internal/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
var version string
|
var version string // kept for ldflags compat with legacy build scripts; prefer internal/version
|
||||||
|
|
||||||
func showVersion() {
|
func showVersion() {
|
||||||
|
// Prefer modern internal/version (ldflags in Makefile + release workflow)
|
||||||
|
if ver.Version != "dev" || ver.Commit != "" {
|
||||||
|
fmt.Println(ver.String())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Fallback for legacy build scripts that only -X main.version=...
|
||||||
fmt.Println(version)
|
fmt.Println(version)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/gmgauthier/gostations/internal/radio"
|
"github.com/gmgauthier/gostations/internal/radio"
|
||||||
|
ver "github.com/gmgauthier/gostations/internal/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestShowVersion_Unit(t *testing.T) {
|
func TestShowVersion_Unit(t *testing.T) {
|
||||||
@ -27,6 +28,7 @@ func TestShowVersion_Unit(t *testing.T) {
|
|||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
// Test legacy main var path
|
||||||
originalVersion := version
|
originalVersion := version
|
||||||
version = tt.version
|
version = tt.version
|
||||||
defer func() { version = originalVersion }()
|
defer func() { version = originalVersion }()
|
||||||
@ -46,7 +48,31 @@ func TestShowVersion_Unit(t *testing.T) {
|
|||||||
got := buf.String()
|
got := buf.String()
|
||||||
|
|
||||||
if got != tt.expected {
|
if got != tt.expected {
|
||||||
t.Errorf("showVersion() = %q, want %q", got, tt.expected)
|
t.Errorf("showVersion() legacy = %q, want %q", got, tt.expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test new internal/version path (preferred for 2.0+ builds)
|
||||||
|
origV := ver.Version
|
||||||
|
origC := ver.Commit
|
||||||
|
ver.Version = tt.version
|
||||||
|
ver.Commit = ""
|
||||||
|
defer func() { ver.Version = origV; ver.Commit = origC }()
|
||||||
|
|
||||||
|
origStdout = os.Stdout
|
||||||
|
r, w, _ = os.Pipe()
|
||||||
|
os.Stdout = w
|
||||||
|
|
||||||
|
showVersion()
|
||||||
|
|
||||||
|
w.Close()
|
||||||
|
os.Stdout = origStdout
|
||||||
|
|
||||||
|
buf.Reset()
|
||||||
|
_, _ = buf.ReadFrom(r)
|
||||||
|
got = buf.String()
|
||||||
|
|
||||||
|
if got != tt.expected {
|
||||||
|
t.Errorf("showVersion() package = %q, want %q", got, tt.expected)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user