feat(release): add automated release workflow and install script
- Embed version info in binaries via ldflags - Create multi-platform builds, archives, and checksums - Add Gitea release creation and asset upload in CI - Introduce GoReleaser config for standardized builds - Add version command and install script for easy deployment - Update README with pre-built installation instructions
This commit is contained in:
parent
b8906e44c1
commit
b8482b6fb0
@ -25,15 +25,48 @@ jobs:
|
|||||||
|
|
||||||
- name: Build for multiple platforms
|
- name: Build for multiple platforms
|
||||||
run: |
|
run: |
|
||||||
GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -trimpath -o build/grokkit-linux-amd64 .
|
VERSION=${GITHUB_REF#refs/tags/}
|
||||||
GOOS=linux GOARCH=arm64 go build -ldflags "-s -w" -trimpath -o build/grokkit-linux-arm64 .
|
COMMIT=$(git rev-parse --short HEAD)
|
||||||
GOOS=darwin GOARCH=amd64 go build -ldflags "-s -w" -trimpath -o build/grokkit-darwin-amd64 .
|
DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||||
GOOS=darwin GOARCH=arm64 go build -ldflags "-s -w" -trimpath -o build/grokkit-darwin-arm64 .
|
mkdir -p build
|
||||||
GOOS=windows GOARCH=amd64 go build -ldflags "-s -w" -trimpath -o build/grokkit-windows-amd64.exe .
|
for plat in 'linux/amd64' 'linux/arm64' 'darwin/amd64' 'darwin/arm64' 'windows/amd64'; do
|
||||||
|
IFS='/' read -r OS ARCH <<< "$plat"
|
||||||
- name: Create Release
|
BIN="grokkit-${OS}-${ARCH}"
|
||||||
uses: softprops/action-gh-release@v1
|
if [ "$OS" = "windows" ]; then BIN="${BIN}.exe"; fi
|
||||||
with:
|
GOOS="$OS" GOARCH="$ARCH" go build -ldflags "-s -w -X 'gmgauthier.com/grokkit/internal/version.Version=${VERSION}' -X 'gmgauthier.com/grokkit/internal/version.Commit=${COMMIT}' -X 'gmgauthier.com/grokkit/internal/version.BuildDate=${DATE}' -trimpath" -o "build/${BIN}" .
|
||||||
files: |
|
done
|
||||||
build/grokkit-*
|
- name: Prepare assets
|
||||||
generate_release_notes: true
|
run: |
|
||||||
|
VERSION=${GITHUB_REF#refs/tags/}
|
||||||
|
for bin in build/grokkit-* ; do
|
||||||
|
if [ ! -f "$bin" ]; then continue; fi
|
||||||
|
OSARCH=$(basename "$bin" | sed 's/grokkit-//' | sed 's/\.exe$//')
|
||||||
|
tar czf "build/grokkit-${OSARCH}-${VERSION}.tar.gz" -C build "$(basename "$bin")"
|
||||||
|
done
|
||||||
|
sha256sum build/grokkit-*.tar.gz | tee build/checksums.txt
|
||||||
|
cp scripts/grokkit-install.sh build/
|
||||||
|
- 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
|
||||||
|
# Create release
|
||||||
|
curl -X POST "${GITEA_API}/repos/${GITHUB_REPOSITORY}/releases" \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"tag_name\": \"${VERSION}\",\"name\": \"Grokkit ${VERSION}\",\"body\": \"## Quick Install\\n\\n```bash\\ncurl -L https://repos.gmgauthier.com/gmgauthier/grokkit/releases/download/v${VERSION}/grokkit-install.sh | VERSION=${VERSION} bash\\n```\\n\\nAssets include platform binaries (tar.gz), checksums.txt. See CHANGELOG.md.\"}" > release.json
|
||||||
|
RELEASE_ID=$(jq .id release.json)
|
||||||
|
# Upload assets
|
||||||
|
for asset in build/* ; do
|
||||||
|
name=$(basename "$asset")
|
||||||
|
mime="application/octet-stream"
|
||||||
|
[[ "$name" =~ \.tar\.gz$ ]] && mime="application/gzip"
|
||||||
|
[[ "$name" =~ \.(txt|sh)$ ]] && mime="text/plain"
|
||||||
|
curl -X POST "${GITEA_API}/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets?name=${name}" \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
|
-H "Content-Type: ${mime}" \
|
||||||
|
--data-binary "@$asset"
|
||||||
|
done
|
||||||
|
|||||||
27
.goreleaser.yaml
Normal file
27
.goreleaser.yaml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
builds:
|
||||||
|
- env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
- darwin
|
||||||
|
- windows
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
|
binary: grokkit
|
||||||
|
ldflags:
|
||||||
|
- -s -w
|
||||||
|
- -X gmgauthier.com/grokkit/internal/version.Version={{.Version}}
|
||||||
|
- -X gmgauthier.com/grokkit/internal/version.Commit={{.Commit}}
|
||||||
|
- -X gmgauthier.com/grokkit/internal/version.BuildDate={{.Date}}
|
||||||
|
- -trimpath
|
||||||
|
|
||||||
|
archives:
|
||||||
|
- format: tar.gz
|
||||||
|
name_template: 'grokkit_{{.Os}}_{{.Arch}}_{{.Version}}.tar.gz'
|
||||||
|
- format: zip
|
||||||
|
name_template: 'grokkit_{{.Os}}_{{.Arch}}_{{.Version}}.zip'
|
||||||
|
os: windows
|
||||||
|
|
||||||
|
checksum:
|
||||||
|
name_template: 'checksums.txt'
|
||||||
@ -23,6 +23,15 @@ make build
|
|||||||
|
|
||||||
# Verify installation
|
# Verify installation
|
||||||
grokkit --help
|
grokkit --help
|
||||||
|
|
||||||
|
### From pre-built release (recommended)
|
||||||
|
```bash
|
||||||
|
VERSION=1.0.0 # Replace with latest version tag (omit 'v')
|
||||||
|
curl -L https://repos.gmgauthier.com/gmgauthier/grokkit/releases/download/v${VERSION}/grokkit-install.sh | VERSION=${VERSION} bash -
|
||||||
|
```
|
||||||
|
Verify:
|
||||||
|
```bash
|
||||||
|
grokkit version
|
||||||
```
|
```
|
||||||
|
|
||||||
## 📋 Table of Contents
|
## 📋 Table of Contents
|
||||||
|
|||||||
11
cmd/root.go
11
cmd/root.go
@ -3,9 +3,11 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"fmt"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"gmgauthier.com/grokkit/config"
|
"gmgauthier.com/grokkit/config"
|
||||||
"gmgauthier.com/grokkit/internal/logger"
|
"gmgauthier.com/grokkit/internal/logger"
|
||||||
|
"gmgauthier.com/grokkit/internal/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
var rootCmd = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
@ -35,6 +37,14 @@ func Execute() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var versionCmd = &cobra.Command{
|
||||||
|
Use: "version",
|
||||||
|
Short: "Print the version information",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Printf("grokkit version %s (commit %s)\\n", version.Version, version.Commit)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(chatCmd)
|
rootCmd.AddCommand(chatCmd)
|
||||||
rootCmd.AddCommand(editCmd)
|
rootCmd.AddCommand(editCmd)
|
||||||
@ -45,6 +55,7 @@ func init() {
|
|||||||
rootCmd.AddCommand(historyCmd)
|
rootCmd.AddCommand(historyCmd)
|
||||||
rootCmd.AddCommand(agentCmd)
|
rootCmd.AddCommand(agentCmd)
|
||||||
rootCmd.AddCommand(completionCmd)
|
rootCmd.AddCommand(completionCmd)
|
||||||
|
rootCmd.AddCommand(versionCmd)
|
||||||
|
|
||||||
// Add model flag to all commands
|
// Add model flag to all commands
|
||||||
rootCmd.PersistentFlags().StringP("model", "m", "", "Grok model to use (overrides config)")
|
rootCmd.PersistentFlags().StringP("model", "m", "", "Grok model to use (overrides config)")
|
||||||
|
|||||||
7
internal/version/version.go
Normal file
7
internal/version/version.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package version
|
||||||
|
|
||||||
|
var (
|
||||||
|
Version = "dev"
|
||||||
|
Commit = ""
|
||||||
|
BuildDate = ""
|
||||||
|
)
|
||||||
50
scripts/grokkit-install.sh
Normal file
50
scripts/grokkit-install.sh
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
VERSION=${VERSION:-${1:?Provide VERSION env or arg, e.g. VERSION=1.0.0 bash grokkit-install.sh}}
|
||||||
|
|
||||||
|
GITEA_BASE=https://repos.gmgauthier.com/gmgauthier/grokkit
|
||||||
|
|
||||||
|
# Detect platform
|
||||||
|
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="grokkit_${OS}_${ARCH}_${VERSION}.tar.gz"
|
||||||
|
|
||||||
|
echo "Installing grokkit ${VERSION} for ${OS}/${ARCH}..."
|
||||||
|
|
||||||
|
TEMP_DIR=$(mktemp -d)
|
||||||
|
trap "rm -rf \"${TEMP_DIR}\"" EXIT
|
||||||
|
|
||||||
|
cd "${TEMP_DIR}"
|
||||||
|
|
||||||
|
# Download
|
||||||
|
curl -fL "${GITEA_BASE}/releases/download/v${VERSION}/${ASSET}" -o asset.tar.gz
|
||||||
|
curl -fL "${GITEA_BASE}/releases/download/v${VERSION}/checksums.txt" -o checksums.txt
|
||||||
|
|
||||||
|
# Verify checksum
|
||||||
|
HASH=$(grep " ${ASSET}$" checksums.txt | cut -d " " -f1)
|
||||||
|
echo "${HASH} asset.tar.gz" | shasum -a 256 --check - || { echo "Checksum mismatch!"; exit 1; }
|
||||||
|
|
||||||
|
# Extract
|
||||||
|
tar xzf asset.tar.gz
|
||||||
|
BINARY="grokkit"
|
||||||
|
|
||||||
|
# Install
|
||||||
|
INSTALL_DIR="${HOME}/.local/bin"
|
||||||
|
mkdir -p "${INSTALL_DIR}"
|
||||||
|
mv "${BINARY}" "${INSTALL_DIR}/grokkit"
|
||||||
|
chmod +x "${INSTALL_DIR}/grokkit"
|
||||||
|
|
||||||
|
echo "✅ grokkit ${VERSION} installed to ${INSTALL_DIR}/grokkit"
|
||||||
|
echo "Add to PATH if needed: export PATH=\"${INSTALL_DIR}:\$PATH\""
|
||||||
|
grokkit version
|
||||||
Loading…
Reference in New Issue
Block a user