From 6dbb70d626ae19f4d48527c5509d6d4e3c7a60bf Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 14:05:22 +0000 Subject: [PATCH] feat(cmd/scm): add custom compile output path Co-Authored-By: Virgil --- cmd/scm/cmd_compile.go | 23 +++++++++++---- cmd/scm/cmd_compile_test.go | 59 +++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 cmd/scm/cmd_compile_test.go diff --git a/cmd/scm/cmd_compile.go b/cmd/scm/cmd_compile.go index 3029a06..c8ece8c 100644 --- a/cmd/scm/cmd_compile.go +++ b/cmd/scm/cmd_compile.go @@ -4,6 +4,7 @@ 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" @@ -18,25 +19,27 @@ func addCompileCommand(parent *cli.Command) { 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.", + 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, signKey, builtBy) + return runCompile(dir, signKey, builtBy, output) }, } cmd.Flags().StringVarP(&dir, "dir", "d", ".", "Project root directory") 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, signKeyHex, builtBy string) error { +func runCompile(dir, signKeyHex, builtBy, output string) error { medium, err := io.NewSandboxed(dir) if err != nil { return cli.WrapVerb(err, "open", dir) @@ -66,8 +69,16 @@ func runCompile(dir, signKeyHex, builtBy string) error { return err } - if err := manifest.WriteCompiled(medium, ".", cm); 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() @@ -79,7 +90,7 @@ func runCompile(dir, signKeyHex, builtBy string) error { 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("core.json")) + cli.Print(" %s %s\n", dimStyle.Render("output:"), valueStyle.Render(output)) cli.Blank() return nil diff --git a/cmd/scm/cmd_compile_test.go b/cmd/scm/cmd_compile_test.go new file mode 100644 index 0000000..182ac39 --- /dev/null +++ b/cmd/scm/cmd_compile_test.go @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: EUPL-1.2 + +package scm + +import ( + filepath "dappco.re/go/core/scm/internal/ax/filepathx" + os "dappco.re/go/core/scm/internal/ax/osx" + "testing" + + "dappco.re/go/core/io" + "dappco.re/go/core/scm/manifest" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestRunCompile_Good_DefaultOutput_Good(t *testing.T) { + dir := t.TempDir() + coreDir := filepath.Join(dir, ".core") + require.NoError(t, os.MkdirAll(coreDir, 0755)) + require.NoError(t, os.WriteFile(filepath.Join(coreDir, "manifest.yaml"), []byte(` +code: compile-default +name: Compile Default +version: 1.0.0 +`), 0644)) + + err := runCompile(dir, "", "core scm compile", "core.json") + require.NoError(t, err) + + raw, err := io.Local.Read(filepath.Join(dir, "core.json")) + require.NoError(t, err) + + cm, err := manifest.ParseCompiled([]byte(raw)) + require.NoError(t, err) + assert.Equal(t, "compile-default", cm.Code) + assert.Equal(t, "core scm compile", cm.BuiltBy) +} + +func TestRunCompile_Good_CustomOutput_Good(t *testing.T) { + dir := t.TempDir() + coreDir := filepath.Join(dir, ".core") + require.NoError(t, os.MkdirAll(coreDir, 0755)) + require.NoError(t, os.WriteFile(filepath.Join(coreDir, "manifest.yaml"), []byte(` +code: compile-custom +name: Compile Custom +version: 2.0.0 +`), 0644)) + + output := filepath.Join("dist", "core.json") + err := runCompile(dir, "", "custom builder", output) + require.NoError(t, err) + + raw, err := io.Local.Read(filepath.Join(dir, output)) + require.NoError(t, err) + + cm, err := manifest.ParseCompiled([]byte(raw)) + require.NoError(t, err) + assert.Equal(t, "compile-custom", cm.Code) + assert.Equal(t, "custom builder", cm.BuiltBy) +}