feat(ninja): publish --bnp uploads a prebuilt wasm artifact (WO-WZ-011)

`ninja plugin publish --bnp <file>` uploads a .bnp built by `ninja plugin
build` instead of a source archive. The orchestrator verifies the .bnp
layout/ABI/name/version server-side and records its abi_version. Without
--bnp, publish keeps shipping a source archive for backwards compatibility
until the CMS install path is wasm-native.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Alex Dunmow 2026-07-03 20:07:57 +08:00
parent ad6d87bf06
commit f708a0269d

View File

@ -679,9 +679,10 @@ func newPluginPublishCmd() *cobra.Command {
var channel string
var strict bool
var privateFlag bool
var bnpFile string
cmd := &cobra.Command{
Use: "publish",
Short: "Build a source archive and publish a new version to the registry",
Short: "Publish a new version to the registry (source archive, or a prebuilt .bnp via --bnp)",
RunE: func(c *cobra.Command, _ []string) error {
host, _ := c.Flags().GetString("host")
cr, err := creds.Load()
@ -751,10 +752,28 @@ func newPluginPublishCmd() *cobra.Command {
return err
}
archiveBytes, err := archive.BuildSourceArchive(".")
// WO-WZ-011: --bnp <file> uploads a prebuilt wasm artifact (from
// `ninja plugin build`) instead of a source archive. The orchestrator
// verifies the .bnp layout/ABI/name/version server-side and records
// its abi_version. Without --bnp, publish keeps shipping a source
// archive (compiled in-container by the CMS reconciler) for
// backwards compatibility until the CMS install path is wasm-native.
var (
archiveBytes []byte
artifactKind = "source archive"
)
if bnpFile != "" {
archiveBytes, err = os.ReadFile(bnpFile)
if err != nil {
return fmt.Errorf("read --bnp file: %w", err)
}
artifactKind = ".bnp artifact"
} else {
archiveBytes, err = archive.BuildSourceArchive(".")
if err != nil {
return fmt.Errorf("build archive: %w", err)
}
}
ctx := context.Background()
getReq := &v1.GetPluginRequest{
@ -784,7 +803,7 @@ func newPluginPublishCmd() *cobra.Command {
if err != nil {
return fmt.Errorf("publish: %w", err)
}
fmt.Printf("Published %s (%d bytes)\n", mod.Coords(), len(archiveBytes))
fmt.Printf("Published %s (%s, %d bytes)\n", mod.Coords(), artifactKind, len(archiveBytes))
for _, w := range pubResp.Msg.Warnings {
fmt.Printf(" warning: %s\n", w)
}
@ -794,6 +813,7 @@ func newPluginPublishCmd() *cobra.Command {
cmd.Flags().StringVar(&channel, "channel", "latest", "Channel to point at this version")
cmd.Flags().BoolVar(&strict, "strict", false, "Fail if the working tree is dirty (default: ship dirty trees via stash-create)")
cmd.Flags().BoolVar(&privateFlag, "private", false, "Publish as a private plugin under your active account's @private namespace")
cmd.Flags().StringVar(&bnpFile, "bnp", "", "Upload a prebuilt .bnp wasm artifact (from `ninja plugin build`) instead of a source archive")
return cmd
}