Compare commits

...

2 Commits

Author SHA1 Message Date
Jiayuan Zhang
509faab19f feat(cli): enhance version command with JSON output and build info
Add --output json flag, build date, Go version, and OS/arch to the
version command. Update Makefile and goreleaser to inject build date.
2026-04-12 02:12:35 +08:00
Jiayuan Zhang
29f7959db7 fix(cli): fix install script failing on repeated runs (#738)
The install script crashed silently on repeated `--local` runs due to
three issues:

1. `REPO_URL` includes `.git` suffix which returns 404 when used for
   GitHub releases API — `grep` found no match, exited 1, and
   `set -euo pipefail` killed the script with no error message.

2. `multica version` outputs "multica 0.1.26 (commit: ...)" but the
   version comparison used the full string, so it never matched the
   release tag and always attempted unnecessary upgrades.

3. Interrupted previous clones left a non-empty directory without
   `.git/`, causing `git clone` to fail on retry.
2026-04-12 01:53:39 +08:00
6 changed files with 55 additions and 11 deletions

View File

@@ -11,6 +11,7 @@ builds:
- -s -w
- -X main.version={{.Version}}
- -X main.commit={{.ShortCommit}}
- -X main.date={{.Date}}
env:
- CGO_ENABLED=0
goos:

View File

@@ -190,10 +190,11 @@ multica:
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo dev)
COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
DATE ?= $(shell date -u '+%Y-%m-%dT%H:%M:%SZ')
build:
cd server && go build -o bin/server ./cmd/server
cd server && go build -ldflags "-X main.version=$(VERSION) -X main.commit=$(COMMIT)" -o bin/multica ./cmd/multica
cd server && go build -ldflags "-X main.version=$(VERSION) -X main.commit=$(COMMIT) -X main.date=$(DATE)" -o bin/multica ./cmd/multica
cd server && go build -o bin/migrate ./cmd/migrate
test:

View File

@@ -13,6 +13,7 @@ set -euo pipefail
# Configuration
# ---------------------------------------------------------------------------
REPO_URL="https://github.com/multica-ai/multica.git"
REPO_WEB_URL="https://github.com/multica-ai/multica" # without .git, for GitHub web APIs
INSTALL_DIR="${MULTICA_INSTALL_DIR:-$HOME/.multica/server}"
BREW_PACKAGE="multica-ai/tap/multica"
@@ -62,10 +63,16 @@ install_cli_brew() {
if ! brew tap multica-ai/tap 2>/dev/null; then
fail "Failed to add Homebrew tap. Check your network connection."
fi
# brew install exits non-zero if already installed on older Homebrew versions
if ! brew install multica 2>/dev/null; then
fail "Failed to install multica via Homebrew."
if brew list multica >/dev/null 2>&1; then
ok "Multica CLI already installed via Homebrew"
else
fail "Failed to install multica via Homebrew."
fi
else
ok "Multica CLI installed via Homebrew"
fi
ok "Multica CLI installed via Homebrew"
}
install_cli_binary() {
@@ -73,7 +80,7 @@ install_cli_binary() {
# Get latest release tag
local latest
latest=$(curl -sI "$REPO_URL/releases/latest" | grep -i '^location:' | sed 's/.*tag\///' | tr -d '\r\n')
latest=$(curl -sI "$REPO_WEB_URL/releases/latest" 2>/dev/null | grep -i '^location:' | sed 's/.*tag\///' | tr -d '\r\n' || true)
if [ -z "$latest" ]; then
fail "Could not determine latest release. Check your network connection."
fi
@@ -123,7 +130,8 @@ add_to_path() {
}
get_latest_version() {
curl -sI "$REPO_URL/releases/latest" 2>/dev/null | grep -i '^location:' | sed 's/.*tag\///' | tr -d '\r\n'
# grep exits 1 when no match; use `|| true` to avoid triggering pipefail
curl -sI "$REPO_WEB_URL/releases/latest" 2>/dev/null | grep -i '^location:' | sed 's/.*tag\///' | tr -d '\r\n' || true
}
upgrade_cli_brew() {
@@ -140,7 +148,8 @@ upgrade_cli_brew() {
install_cli() {
if command_exists multica; then
local current_ver
current_ver=$(multica version 2>/dev/null || echo "unknown")
# `multica version` outputs "multica v0.1.13 (commit: abc1234)" — extract just the version
current_ver=$(multica version 2>/dev/null | awk '{print $2}' || echo "unknown")
local latest_ver
latest_ver=$(get_latest_version)
@@ -162,7 +171,7 @@ install_cli() {
fi
local new_ver
new_ver=$(multica version 2>/dev/null || echo "unknown")
new_ver=$(multica version 2>/dev/null | awk '{print $2}' || echo "unknown")
ok "Multica CLI upgraded ($current_ver$new_ver)"
return 0
fi
@@ -217,6 +226,11 @@ setup_server() {
if ! command_exists git; then
fail "Git is not installed. Please install git and re-run."
fi
# Remove leftover directory from a previously interrupted clone
if [ -d "$INSTALL_DIR" ]; then
warn "Removing incomplete installation at $INSTALL_DIR..."
rm -rf "$INSTALL_DIR"
fi
mkdir -p "$(dirname "$INSTALL_DIR")"
git clone --depth 1 "$REPO_URL" "$INSTALL_DIR"
cd "$INSTALL_DIR"

View File

@@ -17,7 +17,7 @@ var updateCmd = &cobra.Command{
}
func runUpdate(_ *cobra.Command, _ []string) error {
fmt.Fprintf(os.Stderr, "Current version: %s (commit: %s)\n", version, commit)
fmt.Fprintf(os.Stderr, "Current version: %s (commit: %s, built: %s)\n", version, commit, date)
// Check latest version from GitHub.
latest, err := cli.FetchLatestRelease()

View File

@@ -1,15 +1,42 @@
package main
import (
"encoding/json"
"fmt"
"os"
"runtime"
"github.com/spf13/cobra"
)
func init() {
versionCmd.Flags().String("output", "text", "Output format: text or json")
}
var versionCmd = &cobra.Command{
Use: "version",
Short: "Print version information",
Run: func(_ *cobra.Command, _ []string) {
fmt.Printf("multica %s (commit: %s)\n", version, commit)
},
RunE: runVersion,
}
func runVersion(cmd *cobra.Command, _ []string) error {
output, _ := cmd.Flags().GetString("output")
if output == "json" {
info := map[string]string{
"version": version,
"commit": commit,
"date": date,
"go": runtime.Version(),
"os": runtime.GOOS,
"arch": runtime.GOARCH,
}
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
return enc.Encode(info)
}
fmt.Printf("multica %s (commit: %s, built: %s)\n", version, commit, date)
fmt.Printf("go: %s, os/arch: %s/%s\n", runtime.Version(), runtime.GOOS, runtime.GOARCH)
return nil
}

View File

@@ -10,6 +10,7 @@ import (
var (
version = "dev"
commit = "unknown"
date = "unknown"
)
var rootCmd = &cobra.Command{