go-scm/cmd/scm/cmd_compile.go
Virgil de94350f13
Some checks failed
Security Scan / security (push) Failing after 16s
Test / test (push) Failing after 55s
feat(manifest): allow version override during compile
Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-02 14:51:41 +00:00

118 lines
3.3 KiB
Go

// SPDX-License-Identifier: EUPL-1.2
package scm
import (
"crypto/ed25519"
filepath "dappco.re/go/core/scm/internal/ax/filepathx"
strings "dappco.re/go/core/scm/internal/ax/stringsx"
"encoding/hex"
exec "golang.org/x/sys/execabs"
"dappco.re/go/core/io"
"dappco.re/go/core/scm/manifest"
"forge.lthn.ai/core/cli/pkg/cli"
)
func addCompileCommand(parent *cli.Command) {
var (
version string
dir string
signKey string
builtBy string
output string
)
cmd := &cli.Command{
Use: "compile",
Short: "Compile manifest.yaml into core.json",
Long: "Read .core/manifest.yaml, attach build metadata (commit, tag), and write core.json to the project root or a custom output path.",
RunE: func(cmd *cli.Command, args []string) error {
return runCompile(dir, version, signKey, builtBy, output)
},
}
cmd.Flags().StringVarP(&dir, "dir", "d", ".", "Project root directory")
cmd.Flags().StringVar(&version, "version", "", "Override the manifest version")
cmd.Flags().StringVar(&signKey, "sign-key", "", "Hex-encoded ed25519 private key for signing")
cmd.Flags().StringVar(&builtBy, "built-by", "core scm compile", "Builder identity")
cmd.Flags().StringVarP(&output, "output", "o", "core.json", "Output path for the compiled manifest")
parent.AddCommand(cmd)
}
func runCompile(dir, version, signKeyHex, builtBy, output string) error {
medium, err := io.NewSandboxed(dir)
if err != nil {
return cli.WrapVerb(err, "open", dir)
}
m, err := manifest.Load(medium, ".")
if err != nil {
return cli.WrapVerb(err, "load", "manifest")
}
opts := manifest.CompileOptions{
Version: version,
Commit: gitCommit(dir),
Tag: gitTag(dir),
BuiltBy: builtBy,
}
if signKeyHex != "" {
keyBytes, err := hex.DecodeString(signKeyHex)
if err != nil {
return cli.WrapVerb(err, "decode", "sign key")
}
opts.SignKey = ed25519.PrivateKey(keyBytes)
}
cm, err := manifest.Compile(m, opts)
if err != nil {
return err
}
data, err := manifest.MarshalJSON(cm)
if err != nil {
return cli.WrapVerb(err, "marshal", "manifest")
}
if err := medium.EnsureDir(filepath.Dir(output)); err != nil {
return cli.WrapVerb(err, "create", filepath.Dir(output))
}
if err := medium.Write(output, string(data)); err != nil {
return cli.WrapVerb(err, "write", output)
}
cli.Blank()
cli.Print(" %s %s\n", successStyle.Render("compiled"), valueStyle.Render(m.Code))
cli.Print(" %s %s\n", dimStyle.Render("version:"), valueStyle.Render(cm.Version))
if opts.Commit != "" {
cli.Print(" %s %s\n", dimStyle.Render("commit:"), valueStyle.Render(opts.Commit))
}
if opts.Tag != "" {
cli.Print(" %s %s\n", dimStyle.Render("tag:"), valueStyle.Render(opts.Tag))
}
cli.Print(" %s %s\n", dimStyle.Render("output:"), valueStyle.Render(output))
cli.Blank()
return nil
}
// gitCommit returns the current HEAD commit hash, or empty on error.
func gitCommit(dir string) string {
out, err := exec.Command("git", "-C", dir, "rev-parse", "HEAD").Output()
if err != nil {
return ""
}
return strings.TrimSpace(string(out))
}
// gitTag returns the tag pointing at HEAD, or empty if none.
func gitTag(dir string) string {
out, err := exec.Command("git", "-C", dir, "describe", "--tags", "--exact-match", "HEAD").Output()
if err != nil {
return ""
}
return strings.TrimSpace(string(out))
}