Conversion to full YAML

This commit is contained in:
2026-05-13 19:22:07 +02:00
parent 7d286551b3
commit 03e2320788
6 changed files with 475 additions and 166 deletions
+237 -76
View File
@@ -296,27 +296,18 @@ func runBuild(ctx context) error {
if err != nil {
return err
}
if err := runBuildModulePreflight(ctx, p, nil); err != nil {
preflight, err := runBuildModulePreflight(ctx, p, nil)
if err != nil {
return err
}
console := newProjectConsole(ctx, p, "build")
result, err := pipeline.Build(p)
if err != nil {
return err
}
fmt.Fprintf(ctx.stdout, "project: %s\n", p.Config.Module.Name)
fmt.Fprintf(ctx.stdout, "module: %s\n", result.ModulePath)
fmt.Fprintf(ctx.stdout, "resources: %d\n", result.Resources)
if result.TopPackageHAK != "" {
fmt.Fprintf(ctx.stdout, "top package hak: %s\n", result.TopPackageHAK)
fmt.Fprintf(ctx.stdout, "top package tlk: %s\n", result.TopPackageTLK)
}
if len(result.HAKPaths) > 0 {
fmt.Fprintf(ctx.stdout, "hak archives: %d\n", len(result.HAKPaths))
fmt.Fprintf(ctx.stdout, "hak assets: %d\n", result.HAKAssets)
fmt.Fprintf(ctx.stdout, "hak manifest: %s\n", result.Manifest)
}
console.emitBuildResult(result, preflight)
return nil
}
@@ -325,15 +316,16 @@ func runBuildModule(ctx context) error {
if err != nil {
return err
}
console := newProjectConsole(ctx, p, "build-module")
spin.configure(ctx.stderr, console.spinnerEnabled)
spin.start("Build Module: starting")
defer spin.stop()
progress := func(message string) {
if ctx.logLevel == logLevelQuiet {
return
}
spin.linebreak()
fmt.Fprintf(ctx.stdout, "[build-module] %s\n", message)
console.progress(message)
}
if err := runBuildModulePreflight(ctx, p, progress); err != nil {
preflight, err := runBuildModulePreflight(ctx, p, progress)
if err != nil {
return err
}
@@ -344,26 +336,36 @@ func runBuildModule(ctx context) error {
return err
}
fmt.Fprintf(ctx.stdout, "project: %s\n", p.Config.Module.Name)
fmt.Fprintf(ctx.stdout, "module: %s\n", result.ModulePath)
fmt.Fprintf(ctx.stdout, "resources: %d\n", result.Resources)
console.emitBuildModuleResult(result, preflight)
return nil
}
func runBuildModulePreflight(ctx context, p *project.Project, progress func(string)) error {
type buildModulePreflightResult struct {
ManifestStatus string
ManifestPath string
ScriptCompilationStatus string
}
func runBuildModulePreflight(ctx context, p *project.Project, progress func(string)) (buildModulePreflightResult, error) {
result := buildModulePreflightResult{}
if progress == nil {
progress = func(string) {}
}
if err := refreshBuildModuleManifest(ctx, p, progress); err != nil {
return err
manifestStatus, manifestPath, err := refreshBuildModuleManifest(ctx, p, progress)
if err != nil {
return result, err
}
if err := prepareBuildModuleCompiler(ctx, p, progress); err != nil {
return err
result.ManifestStatus = manifestStatus
result.ManifestPath = manifestPath
scriptStatus, err := prepareBuildModuleCompiler(ctx, p, progress)
if err != nil {
return result, err
}
return nil
result.ScriptCompilationStatus = scriptStatus
return result, nil
}
func refreshBuildModuleManifest(ctx context, p *project.Project, progress func(string)) error {
func refreshBuildModuleManifest(ctx context, p *project.Project, progress func(string)) (string, string, error) {
manifestPath := p.HAKManifestPath()
if override := strings.TrimSpace(os.Getenv("SOW_HAK_MANIFEST_PATH")); override != "" {
manifestPath = override
@@ -374,36 +376,36 @@ func refreshBuildModuleManifest(ctx context, p *project.Project, progress func(s
if envEnabled("SOW_MODULE_SKIP_HAK_MANIFEST_REFRESH") {
if _, err := os.Stat(manifestPath); err != nil {
return fmt.Errorf("SOW_MODULE_SKIP_HAK_MANIFEST_REFRESH is set, but %s does not exist", manifestPath)
return "", "", fmt.Errorf("SOW_MODULE_SKIP_HAK_MANIFEST_REFRESH is set, but %s does not exist", manifestPath)
}
progress(fmt.Sprintf("Using existing hak manifest at %s; skipping published sow-assets refresh.", relPathFromRoot(p.Root, manifestPath)))
return nil
return "reused", manifestPath, nil
}
progress("Refreshing hak list from the latest published sow-assets manifest...")
if err := runProjectScript(ctx, p, []string{"scripts", "fetch-hak-manifest"}, manifestPath); err != nil {
return err
return "", "", err
}
if _, err := pipeline.ApplyHAKManifest(p, manifestPath); err != nil {
return err
return "", "", err
}
return nil
return "refreshed", manifestPath, nil
}
func prepareBuildModuleCompiler(ctx context, p *project.Project, progress func(string)) error {
func prepareBuildModuleCompiler(ctx context, p *project.Project, progress func(string)) (string, error) {
if envEnabled("SOW_MODULE_SKIP_NSS_COMPILATION") {
progress("SOW_MODULE_SKIP_NSS_COMPILATION is set; skipping NWScript compiler resolution and NSS compilation for this run.")
return nil
return "skipped", nil
}
if !projectHasScriptSources(p) {
return nil
return "not-needed", nil
}
compilerPathEnv := p.ScriptCompilerPathEnv()
explicitCompiler := strings.TrimSpace(os.Getenv(compilerPathEnv))
if explicitCompiler != "" {
if scriptCompilerRunnable(explicitCompiler) {
return nil
return "enabled", nil
}
if fileExists(explicitCompiler) {
return disableBuildModuleCompiler(compilerPathEnv, progress, fmt.Sprintf("Configured NWScript compiler is present but cannot start: %s", explicitCompiler))
@@ -411,7 +413,7 @@ func prepareBuildModuleCompiler(ctx context, p *project.Project, progress func(s
}
if _, ok := findUsableBuildModuleCompiler(p); ok {
return nil
return "enabled", nil
}
installScript := projectScriptPath(p.Root, "scripts", "install-script-compiler")
@@ -424,21 +426,21 @@ func prepareBuildModuleCompiler(ctx context, p *project.Project, progress func(s
return disableBuildModuleCompiler(compilerPathEnv, progress, "Automatic NWScript compiler install failed.")
}
if _, ok := findUsableBuildModuleCompiler(p); ok {
return nil
return "installed", nil
}
return disableBuildModuleCompiler(compilerPathEnv, progress, "Installed NWScript compiler but it still cannot start.")
}
func disableBuildModuleCompiler(compilerPathEnv string, progress func(string), reason string) error {
func disableBuildModuleCompiler(compilerPathEnv string, progress func(string), reason string) (string, error) {
if err := os.Setenv("SOW_MODULE_SKIP_NSS_COMPILATION", "1"); err != nil {
return fmt.Errorf("set SOW_MODULE_SKIP_NSS_COMPILATION: %w", err)
return "", fmt.Errorf("set SOW_MODULE_SKIP_NSS_COMPILATION: %w", err)
}
progress("Skipping NWScript compilation for this build. " + reason)
if compilerPathEnv != "" {
_ = os.Unsetenv(compilerPathEnv)
}
return nil
return "skipped", nil
}
func projectHasScriptSources(p *project.Project) bool {
@@ -585,6 +587,190 @@ const (
logLevelDebug
)
type projectConsole struct {
stdout io.Writer
projectRoot string
projectName string
commandName string
commandLabel string
level logLevel
spinnerEnabled bool
}
func newProjectConsole(ctx context, p *project.Project, commandName string) *projectConsole {
return &projectConsole{
stdout: ctx.stdout,
projectRoot: p.Root,
projectName: p.Config.Module.Name,
commandName: commandName,
commandLabel: projectCommandLabel(commandName),
level: ctx.logLevel,
spinnerEnabled: isInteractiveTTY(ctx.stderr) && strings.TrimSpace(os.Getenv("CI")) == "" && ctx.logLevel == logLevelNormal,
}
}
func projectCommandLabel(commandName string) string {
switch commandName {
case "build":
return "Build"
case "build-module":
return "Build Module"
case "extract":
return "Extract"
case "validate":
return "Validate"
case "compare":
return "Compare"
case "apply-hak-manifest":
return "Apply HAK Manifest"
default:
return commandName
}
}
func (c *projectConsole) progress(message string) {
if phase := c.phaseLabel(message); phase != "" {
spin.update(c.commandLabel + ": " + phase)
}
if c.level != logLevelDebug {
return
}
spin.linebreak()
fmt.Fprintf(c.stdout, "[debug] %s\n", message)
}
func (c *projectConsole) phaseLabel(message string) string {
switch {
case strings.HasPrefix(message, "Refreshing hak list from the latest published sow-assets manifest"):
return "refreshing HAK manifest"
case strings.HasPrefix(message, "Using existing hak manifest at "):
return "reusing HAK manifest"
case strings.HasPrefix(message, "NWScript compiler not found locally. Installing it now"):
return "installing script compiler"
case strings.HasPrefix(message, "Skipping NWScript compilation for this build."):
return "skipping script compilation"
case strings.HasPrefix(message, "Validating project"):
return "validating project"
case strings.HasPrefix(message, "Resolving module HAK order"):
return "resolving HAK order"
case strings.HasPrefix(message, "Collecting module resources"):
return "collecting module resources"
case strings.HasPrefix(message, "Writing module archive"):
return "writing module archive"
default:
return ""
}
}
func (c *projectConsole) emitBuildResult(result pipeline.BuildResult, preflight buildModulePreflightResult) {
spin.linebreak()
fmt.Fprintln(c.stdout, "Build ----------")
fmt.Fprintf(c.stdout, "project: %s\n", c.projectName)
fmt.Fprintf(c.stdout, "module: %s\n", c.relPath(result.ModulePath))
fmt.Fprintf(c.stdout, "resources: %d\n", result.Resources)
if preflight.ManifestStatus != "" {
fmt.Fprintf(c.stdout, "hak manifest: %s", preflight.ManifestStatus)
if preflight.ManifestPath != "" {
fmt.Fprintf(c.stdout, " (%s)", c.relPath(preflight.ManifestPath))
}
fmt.Fprintln(c.stdout)
}
if preflight.ScriptCompilationStatus != "" && preflight.ScriptCompilationStatus != "not-needed" {
fmt.Fprintf(c.stdout, "script compilation: %s\n", preflight.ScriptCompilationStatus)
}
if result.TopPackageHAK != "" {
fmt.Fprintf(c.stdout, "top package hak: %s\n", c.relPath(result.TopPackageHAK))
fmt.Fprintf(c.stdout, "top package tlk: %s\n", c.relPath(result.TopPackageTLK))
}
if len(result.HAKPaths) > 0 {
fmt.Fprintf(c.stdout, "hak archives: %d\n", len(result.HAKPaths))
fmt.Fprintf(c.stdout, "hak assets: %d\n", result.HAKAssets)
fmt.Fprintf(c.stdout, "hak manifest: %s\n", c.relPath(result.Manifest))
}
}
func (c *projectConsole) emitBuildModuleResult(result pipeline.BuildResult, preflight buildModulePreflightResult) {
spin.linebreak()
fmt.Fprintln(c.stdout, "Build Module ----------")
fmt.Fprintf(c.stdout, "project: %s\n", c.projectName)
fmt.Fprintf(c.stdout, "module: %s\n", c.relPath(result.ModulePath))
fmt.Fprintf(c.stdout, "resources: %d\n", result.Resources)
if preflight.ManifestStatus != "" {
fmt.Fprintf(c.stdout, "hak manifest: %s", preflight.ManifestStatus)
if preflight.ManifestPath != "" {
fmt.Fprintf(c.stdout, " (%s)", c.relPath(preflight.ManifestPath))
}
fmt.Fprintln(c.stdout)
}
if preflight.ScriptCompilationStatus != "" && preflight.ScriptCompilationStatus != "not-needed" {
fmt.Fprintf(c.stdout, "script compilation: %s\n", preflight.ScriptCompilationStatus)
}
}
func (c *projectConsole) emitExtractResult(result pipeline.ExtractResult) {
spin.linebreak()
fmt.Fprintln(c.stdout, "Extract ----------")
fmt.Fprintf(c.stdout, "project: %s\n", c.projectName)
fmt.Fprintf(c.stdout, "module: %s\n", c.relPath(result.ModulePath))
if len(result.HAKPaths) > 0 {
fmt.Fprintf(c.stdout, "hak archives: %d\n", len(result.HAKPaths))
}
if len(result.DeletedArchivePaths) > 0 {
fmt.Fprintf(c.stdout, "deleted archives: %d\n", len(result.DeletedArchivePaths))
}
fmt.Fprintf(c.stdout, "written: %d\n", result.Written)
fmt.Fprintf(c.stdout, "overwritten: %d\n", result.Overwritten)
fmt.Fprintf(c.stdout, "removed: %d\n", result.Removed)
fmt.Fprintf(c.stdout, "skipped: %d\n", result.Skipped)
}
func (c *projectConsole) emitValidationResult(report validator.Report, root string, inventoryReport project.InventoryReport) {
spin.linebreak()
fmt.Fprintln(c.stdout, "Validate ----------")
fmt.Fprintf(c.stdout, "project: %s\n", c.projectName)
fmt.Fprintf(c.stdout, "root: %s\n", c.relPath(root))
fmt.Fprintf(c.stdout, "source files: %d\n", inventoryReport.SourceFiles)
fmt.Fprintf(c.stdout, "script files: %d\n", inventoryReport.ScriptFiles)
fmt.Fprintf(c.stdout, "asset files: %d\n", inventoryReport.AssetFiles)
fmt.Fprintf(c.stdout, "module file types: %s\n", strings.Join(inventoryReport.Extensions, ", "))
if warnings := report.WarningCount(); warnings > 0 {
fmt.Fprintf(c.stdout, "warnings: %d\n", warnings)
}
fmt.Fprintln(c.stdout, "validation: ok")
}
func (c *projectConsole) emitCompareResult(result pipeline.CompareResult) {
spin.linebreak()
fmt.Fprintln(c.stdout, "Compare ----------")
fmt.Fprintf(c.stdout, "project: %s\n", c.projectName)
fmt.Fprintf(c.stdout, "module: %s\n", c.relPath(result.ModulePath))
if len(result.HAKPaths) > 0 {
fmt.Fprintf(c.stdout, "hak archives: %d\n", len(result.HAKPaths))
}
fmt.Fprintf(c.stdout, "checked resources: %d\n", result.Checked)
fmt.Fprintln(c.stdout, "compare: ok")
}
func (c *projectConsole) emitApplyManifestResult(result pipeline.ApplyManifestResult) {
spin.linebreak()
fmt.Fprintln(c.stdout, "Apply HAK Manifest ----------")
fmt.Fprintf(c.stdout, "project: %s\n", c.projectName)
fmt.Fprintf(c.stdout, "manifest: %s\n", c.relPath(result.ManifestPath))
fmt.Fprintf(c.stdout, "module source: %s\n", c.relPath(result.ModuleSource))
fmt.Fprintf(c.stdout, "hak entries: %d\n", result.HAKCount)
}
func (c *projectConsole) relPath(path string) string {
if path == "" {
return path
}
rel, err := filepath.Rel(c.projectRoot, path)
if err != nil {
return filepath.ToSlash(path)
}
return filepath.ToSlash(rel)
}
type buildHAKConsole struct {
stdout io.Writer
projectRoot string
@@ -1230,6 +1416,7 @@ func runExtract(ctx context) error {
if err != nil {
return err
}
console := newProjectConsole(ctx, p, "extract")
files := ctx.args[1:]
result, err := pipeline.Extract(p, files...)
@@ -1237,18 +1424,7 @@ func runExtract(ctx context) error {
return err
}
fmt.Fprintf(ctx.stdout, "project: %s\n", p.Config.Module.Name)
fmt.Fprintf(ctx.stdout, "module: %s\n", result.ModulePath)
if len(result.HAKPaths) > 0 {
fmt.Fprintf(ctx.stdout, "hak archives: %d\n", len(result.HAKPaths))
}
if len(result.DeletedArchivePaths) > 0 {
fmt.Fprintf(ctx.stdout, "deleted archives: %d\n", len(result.DeletedArchivePaths))
}
fmt.Fprintf(ctx.stdout, "written: %d\n", result.Written)
fmt.Fprintf(ctx.stdout, "overwritten: %d\n", result.Overwritten)
fmt.Fprintf(ctx.stdout, "removed: %d\n", result.Removed)
fmt.Fprintf(ctx.stdout, "skipped: %d\n", result.Skipped)
console.emitExtractResult(result)
return nil
}
@@ -1257,6 +1433,7 @@ func runValidate(ctx context) error {
if err != nil {
return err
}
console := newProjectConsole(ctx, p, "validate")
validationReport := validator.ValidateProject(p)
emitValidatorReport(ctx.stderr, validationReport)
@@ -1265,16 +1442,7 @@ func runValidate(ctx context) error {
}
inventoryReport := p.Inventory.Report()
fmt.Fprintf(ctx.stdout, "project: %s\n", p.Config.Module.Name)
fmt.Fprintf(ctx.stdout, "root: %s\n", p.Root)
fmt.Fprintf(ctx.stdout, "source files: %d\n", inventoryReport.SourceFiles)
fmt.Fprintf(ctx.stdout, "script files: %d\n", inventoryReport.ScriptFiles)
fmt.Fprintf(ctx.stdout, "asset files: %d\n", inventoryReport.AssetFiles)
fmt.Fprintf(ctx.stdout, "module file types: %s\n", strings.Join(inventoryReport.Extensions, ", "))
if warnings := validationReport.WarningCount(); warnings > 0 {
fmt.Fprintf(ctx.stdout, "warnings: %d\n", warnings)
}
fmt.Fprintf(ctx.stdout, "validation: ok\n")
console.emitValidationResult(validationReport, p.Root, inventoryReport)
return nil
}
@@ -1480,19 +1648,14 @@ func runCompare(ctx context) error {
if err != nil {
return err
}
console := newProjectConsole(ctx, p, "compare")
result, err := pipeline.Compare(p)
if err != nil {
return err
}
fmt.Fprintf(ctx.stdout, "project: %s\n", p.Config.Module.Name)
fmt.Fprintf(ctx.stdout, "module: %s\n", result.ModulePath)
if len(result.HAKPaths) > 0 {
fmt.Fprintf(ctx.stdout, "hak archives: %d\n", len(result.HAKPaths))
}
fmt.Fprintf(ctx.stdout, "checked resources: %d\n", result.Checked)
fmt.Fprintf(ctx.stdout, "compare: ok\n")
console.emitCompareResult(result)
return nil
}
@@ -1501,6 +1664,7 @@ func runApplyHAKManifest(ctx context) error {
if err != nil {
return err
}
console := newProjectConsole(ctx, p, "apply-hak-manifest")
manifestPath := p.HAKManifestPath()
if len(ctx.args) > 1 {
@@ -1515,10 +1679,7 @@ func runApplyHAKManifest(ctx context) error {
return err
}
fmt.Fprintf(ctx.stdout, "project: %s\n", p.Config.Module.Name)
fmt.Fprintf(ctx.stdout, "manifest: %s\n", result.ManifestPath)
fmt.Fprintf(ctx.stdout, "module source: %s\n", result.ModuleSource)
fmt.Fprintf(ctx.stdout, "hak entries: %d\n", result.HAKCount)
console.emitApplyManifestResult(result)
return nil
}