nats-exec: move out
This commit is contained in:
@@ -38,5 +38,6 @@ inputs:
|
|||||||
required: false
|
required: false
|
||||||
default: 'false'
|
default: 'false'
|
||||||
runs:
|
runs:
|
||||||
|
# noinspection YAMLSchemaValidation
|
||||||
using: 'go'
|
using: 'go'
|
||||||
main: 'cmd/nats-upload/main.go'
|
main: 'main.go'
|
||||||
|
|||||||
@@ -1,155 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/nats-io/nats.go"
|
|
||||||
"github.com/nats-io/nats.go/jetstream"
|
|
||||||
"golang.org/x/mod/semver"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if len(os.Args) < 2 {
|
|
||||||
_, _ = fmt.Fprintf(os.Stderr, "Usage: %s <binary-name> [args...]\n", os.Args[0])
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
binaryName := os.Args[1]
|
|
||||||
remainingArgs := os.Args[2:]
|
|
||||||
|
|
||||||
natsURL := getEnv("NATS_URL", "nats://localhost:4222")
|
|
||||||
bucketName := getEnv("NATS_BUCKET", "binaries")
|
|
||||||
cacheDir := getEnv("NATS_CACHE_DIR", filepath.Join(os.TempDir(), "nats-exec-cache"))
|
|
||||||
natsDomain := getEnv("NATS_JS_DOMAIN", "")
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
nc, err := nats.Connect(natsURL)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to connect to NATS: %v", err)
|
|
||||||
}
|
|
||||||
defer nc.Close()
|
|
||||||
|
|
||||||
js, err := createJetStream(nc, natsDomain)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to create JetStream context: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
store, err := js.ObjectStore(ctx, bucketName)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to get object store %s: %v", bucketName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format: binary/arch/version
|
|
||||||
arch := runtime.GOARCH
|
|
||||||
|
|
||||||
objects, err := store.List(ctx)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to list objects: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var latestVersion string
|
|
||||||
var latestKey string
|
|
||||||
|
|
||||||
for _, info := range objects {
|
|
||||||
// Key structure: <binaryName>/<arch>/<version>
|
|
||||||
|
|
||||||
parts := strings.Split(info.Name, "/")
|
|
||||||
if len(parts) != 3 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if parts[0] != binaryName {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if parts[1] != arch {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
version := parts[2]
|
|
||||||
if !strings.HasPrefix(version, "v") {
|
|
||||||
version = "v" + version
|
|
||||||
}
|
|
||||||
|
|
||||||
if semver.IsValid(version) {
|
|
||||||
if latestVersion == "" || semver.Compare(version, latestVersion) > 0 {
|
|
||||||
latestVersion = version
|
|
||||||
latestKey = info.Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if latestKey == "" {
|
|
||||||
log.Fatalf("No version of %s found for arch %s", binaryName, arch)
|
|
||||||
}
|
|
||||||
|
|
||||||
localPath := filepath.Join(cacheDir, latestKey)
|
|
||||||
|
|
||||||
if _, err := os.Stat(localPath); os.IsNotExist(err) {
|
|
||||||
log.Printf("Downloading %s version %s...", binaryName, latestVersion)
|
|
||||||
if err := downloadBinary(ctx, store, latestKey, localPath); err != nil {
|
|
||||||
log.Fatalf("Failed to download binary: %v", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Printf("Using cached %s version %s", binaryName, latestVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := os.Chmod(localPath, 0755); err != nil {
|
|
||||||
log.Fatalf("Failed to make binary executable: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fullPath, err := filepath.Abs(localPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to get absolute path: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
env := os.Environ()
|
|
||||||
args := append([]string{fullPath}, remainingArgs...)
|
|
||||||
|
|
||||||
err = syscall.Exec(fullPath, args, env)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to exec %s: %v", fullPath, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func downloadBinary(ctx context.Context, store jetstream.ObjectStore, key, localPath string) error {
|
|
||||||
if err := os.MkdirAll(filepath.Dir(localPath), 0755); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
obj, err := store.Get(ctx, key)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.OpenFile(localPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0755)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
_, err = io.Copy(f, obj)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func getEnv(key, defaultValue string) string {
|
|
||||||
if value, ok := os.LookupEnv(key); ok {
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
return defaultValue
|
|
||||||
}
|
|
||||||
|
|
||||||
func createJetStream(nc *nats.Conn, domain string) (jetstream.JetStream, error) {
|
|
||||||
if domain != "" {
|
|
||||||
return jetstream.NewWithDomain(nc, domain)
|
|
||||||
}
|
|
||||||
|
|
||||||
return jetstream.New(nc)
|
|
||||||
}
|
|
||||||
4
justfile
4
justfile
@@ -59,13 +59,13 @@ build GOOS GOARCH:
|
|||||||
-ldflags {{LD_FLAGS}} {{GO_OPTS}} \
|
-ldflags {{LD_FLAGS}} {{GO_OPTS}} \
|
||||||
-mod mod \
|
-mod mod \
|
||||||
-o bin/{{OUTBIN}}{{SUFFIX}}_{{GOOS}}_{{GOARCH}} \
|
-o bin/{{OUTBIN}}{{SUFFIX}}_{{GOOS}}_{{GOARCH}} \
|
||||||
./cmd/{{OUTBIN}}/main.go
|
./main.go
|
||||||
build-race:
|
build-race:
|
||||||
GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go build -race \
|
GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go build -race \
|
||||||
-ldflags {{LD_FLAGS}} {{GO_OPTS}} \
|
-ldflags {{LD_FLAGS}} {{GO_OPTS}} \
|
||||||
-mod mod \
|
-mod mod \
|
||||||
-o bin/{{OUTBIN}}{{SUFFIX}}_linux_amd64 \
|
-o bin/{{OUTBIN}}{{SUFFIX}}_linux_amd64 \
|
||||||
./cmd/{{OUTBIN}}/main.go
|
./main.go
|
||||||
|
|
||||||
# Install binaries
|
# Install binaries
|
||||||
install:
|
install:
|
||||||
|
|||||||
Reference in New Issue
Block a user