Files
fchengyan 52ced3710f fix(build): embed commit SHA for release provenance (#1571 part 2) (#1590)
* fix(build): embed commit SHA for release provenance (#1571 part 2)

Docker builds exclude .git via .dockerignore, so buildvcs cannot read
VCS metadata and published images carry no commit information. A running
image cannot be lined up with the source commit it was built from.

Embed cmd.CommitSHA at link time (maintainer-endorsed option 2) and
surface it in goclaw version output:

- cmd: add CommitSHA var, print commit in version cmd when injected
- Makefile: pass git rev-parse HEAD via LDFLAGS
- Dockerfile: accept COMMIT_SHA build arg (default unknown)
- docker-compose.yml: pass GOCLAW_COMMIT_SHA through as build arg
- release workflows: inject github.sha into release and dev-beta builds

Backward compatible: binaries built without the flag keep the existing
version output format.

* fix(build): pass COMMIT_SHA to docker image builds, surface it in doctor/upgrade

Review follow-up for PR #1590:

- Add COMMIT_SHA=${{ github.sha }} to the build-args of every
  docker/build-push-action step (release.yaml, dev-beta-release.yaml,
  release-beta.yaml, fork-image.yaml) so published images — the
  artifact issue #1571 is about — carry the commit, not just release
  tarball binaries.
- Surface the commit in doctor and upgrade output (App version line)
  via a shared commitSuffix() helper, so operators can read provenance
  from logs without exec'ing goclaw version (review suggestion #2).
- version cmd refactored onto the same helper; output unchanged.
2026-09-30 15:38:53 +07:00

103 lines
3.0 KiB
Go

package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/nextlevelbuilder/goclaw/pkg/protocol"
)
// Version is set at build time via -ldflags "-X github.com/nextlevelbuilder/goclaw/cmd.Version=v1.0.0"
var Version = "dev"
// CommitSHA is set at build time via -ldflags "-X github.com/nextlevelbuilder/goclaw/cmd.CommitSHA=<sha>".
// It records the exact source commit the binary was built from, so a running
// image/binary can be lined up with a commit even when VCS metadata is
// unavailable (e.g. Docker builds, where .git is excluded from the context).
var CommitSHA = "unknown"
// commitSuffix returns " (commit <sha>)" when CommitSHA was injected at build
// time, so version/doctor/upgrade output can carry release provenance.
func commitSuffix() string {
if CommitSHA == "" || CommitSHA == "unknown" {
return ""
}
return " (commit " + CommitSHA + ")"
}
var (
cfgFile string
verbose bool
gatewayServerOverride string
gatewayTokenOverride string
gatewayOutputFormat string
)
var rootCmd = &cobra.Command{
Use: "goclaw",
Short: "GoClaw — AI agent gateway",
Long: "GoClaw: multi-agent AI platform with WebSocket RPC, tool execution, and channel integration. A Go port of OpenClaw with enhanced security and multi-tenant support.",
Run: func(cmd *cobra.Command, args []string) {
runGateway()
},
}
func init() {
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default: config.json or $GOCLAW_CONFIG)")
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "enable debug logging")
rootCmd.PersistentFlags().StringVar(&gatewayServerOverride, "server", "", "gateway server URL override")
rootCmd.PersistentFlags().StringVar(&gatewayTokenOverride, "token", "", "gateway bearer token override")
rootCmd.AddCommand(onboardCmd())
rootCmd.AddCommand(versionCmd())
rootCmd.AddCommand(pairingCmd())
rootCmd.AddCommand(agentCmd())
rootCmd.AddCommand(doctorCmd())
rootCmd.AddCommand(configCmd())
rootCmd.AddCommand(providersCmd())
rootCmd.AddCommand(channelsCmd())
rootCmd.AddCommand(bitrixPortalCmd())
rootCmd.AddCommand(cronCmd())
rootCmd.AddCommand(skillsCmd())
rootCmd.AddCommand(sessionsCmd())
rootCmd.AddCommand(tracesCmd())
rootCmd.AddCommand(migrateCmd())
rootCmd.AddCommand(upgradeCmd())
rootCmd.AddCommand(backupCmd())
rootCmd.AddCommand(restoreCmd())
rootCmd.AddCommand(tenantBackupCmd())
rootCmd.AddCommand(tenantRestoreCmd())
rootCmd.AddCommand(authCmd())
rootCmd.AddCommand(setupCmd())
}
func versionCmd() *cobra.Command {
return &cobra.Command{
Use: "version",
Short: "Print version information",
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("goclaw %s%s (protocol %d)\n", Version, commitSuffix(), protocol.ProtocolVersion)
},
}
}
func resolveConfigPath() string {
if cfgFile != "" {
return cfgFile
}
if v := os.Getenv("GOCLAW_CONFIG"); v != "" {
return v
}
return "config.json"
}
// Execute runs the root cobra command.
func Execute() {
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
}
}