Skip to content

Add lint-package debug command for engines, runtimes and models#394

Open
mrmara wants to merge 4 commits into
mainfrom
IENG-2491-models-runtimes-validation
Open

Add lint-package debug command for engines, runtimes and models#394
mrmara wants to merge 4 commits into
mainfrom
IENG-2491-models-runtimes-validation

Conversation

@mrmara

@mrmara mrmara commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

lint-package command checks and validate manifests file for engines, runtimes and models

Example usage:
go run ./cmd/modelctl debug lint-package <snap-directory>

Test:

Succesful

go run ./cmd/modelctl debug lint-package ../qwen3.5
✅ ../qwen3.5/engines/cpu/engine.yaml
✅ ../qwen3.5/engines/nvidia-gpu/engine.yaml
✅ ../qwen3.5/models/4b-q4-k-xl-gguf/model.yaml
✅ ../qwen3.5/models/9b-q4-k-m-gguf/model.yaml
✅ ../qwen3.5/runtimes/llamacpp/runtime.yaml
✅ ../qwen3.5/runtimes/llamacpp-cuda/runtime.yaml

Fail since models, runtimes nor engines directories are found:

go run ./cmd/modelctl debug lint-package .
❌ engines: no manifests found
❌ models: no manifests found
❌ runtimes: no manifests found
Error: not all manifests are valid
exit status 1

Fail since models directory is not found:

go run ./cmd/modelctl debug lint-package ../qwen3.5-another/
✅ ../qwen3.5-another/engines/cpu/engine.yaml
✅ ../qwen3.5-another/engines/nvidia-gpu/engine.yaml
❌ ../qwen3.5-another/models: no manifests found
✅ ../qwen3.5-another/runtimes/llamacpp/runtime.yaml
✅ ../qwen3.5-another/runtimes/llamacpp-cuda/runtime.yaml
Error: not all manifests are valid
exit status 1

Fail because of validation error on a manifest:

go run ./cmd/modelctl debug lint-package ../qwen3.5-another/
✅ ../qwen3.5-another/engines/cpu/engine.yaml
✅ ../qwen3.5-another/engines/nvidia-gpu/engine.yaml
❌ ../qwen3.5-another/models/qwen-3-5-4b-q4-k-xm/model.yaml: model directory name should match name in manifest: qwen-3-5-4b-q4-k-xm != Qwen 3.5 4B
✅ ../qwen3.5-another/models/qwen-3-5-9b-q4-k-m/model.yaml
✅ ../qwen3.5-another/runtimes/llamacpp/runtime.yaml
✅ ../qwen3.5-another/runtimes/llamacpp-cuda/runtime.yaml
Error: not all manifests are valid
exit status 1

Fail because of webui unsupported model capabilities:

go run ./cmd/modelctl debug lint-package ../qwen3.5
✅ ../qwen3.5/engines/cpu/engine.yaml
✅ ../qwen3.5/engines/nvidia-gpu/engine.yaml
❌ ../qwen3.5/models/4b-q4-k-xl-gguf/model.yaml: unsupported capability: "thinking"
❌ ../qwen3.5/models/9b-q4-k-m-gguf/model.yaml: unsupported capability: "thinking"
✅ ../qwen3.5/runtimes/llamacpp/runtime.yaml
✅ ../qwen3.5/runtimes/llamacpp-cuda/runtime.yaml
Error: not all manifests are valid
exit status 1

Suggested change in workflows:

go run . debug validate-engines ../../../engines/**/*.yaml
go run . debug lint-package ../../../

Copilot AI review requested due to automatic review settings July 8, 2026 10:25

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a modelctl debug lint-package <snap-directory> command to lint/validate manifest YAMLs across an entire snap package layout (engines/models/runtimes), and introduces dedicated validators + tests for model and runtime manifests.

Changes:

  • Add YAML manifest validators for pkg/models and pkg/runtimes (unknown-field detection, required-field checks, directory-name consistency checks).
  • Add test suites to validate real manifests under test_data/ and validate key error cases (empty YAML, unknown fields, missing required fields).
  • Update cmd/modelctl debug command from validate-engines to lint-package, scanning a snap directory for manifests and reporting per-file results.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
cmd/modelctl/commands/debug/validate.go Implements lint-package command to discover and validate manifests under engines/models/runtimes.
pkg/models/validate.go Adds model manifest YAML validation and directory-name matching logic.
pkg/models/validate_test.go Adds tests for model manifest validation and required fields.
pkg/runtimes/validate.go Adds runtime manifest YAML validation and directory-name matching logic.
pkg/runtimes/validate_test.go Adds tests for runtime manifest validation and required fields.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pkg/models/validate.go
Comment thread pkg/models/validate.go
Comment thread pkg/models/validate.go
Comment thread cmd/modelctl/commands/debug/validate.go Outdated
Comment thread cmd/modelctl/commands/debug/validate.go

@farshidtz farshidtz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great to have the validation coverage gap reduced.

Comment on lines +47 to +58
for _, v := range validators {
pattern := filepath.Join(snapDir, v.subdir, "*", v.manifestFilename)
manifestPaths, err := filepath.Glob(pattern)
if err != nil {
return fmt.Errorf("invalid glob pattern %s: %w", pattern, err)
}

if len(manifestPaths) == 0 {
allManifestsValid = false
fmt.Printf("❌ %s: %s\n", manifestPath, err)
} else {
fmt.Printf("✅ %s\n", manifestPath)
fmt.Printf("❌ %s: no manifests found\n", filepath.Join(snapDir, v.subdir))
continue
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would consider both runtimes and models optional. There could be an engine without a runtime, delivering just optimized weights or an engine with a combined runtime+model, using llamafiles. I see runtimes and models treated as an expected fields for engines elsewhere in the code so there has been an architectural regression. In this case, let's leave this for now.

Comment thread pkg/models/validate.go
Comment on lines +89 to +91
if manifest.ModelCardUrl == "" {
return fmt.Errorf("required field is not set: model-card-url")
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validate URL. (url.Parse)

Comment thread pkg/models/validate.go

if manifest.DiskSize == "" {
return fmt.Errorf("required field is not set: disk-size")
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validate input format / suffix.

Comment thread pkg/models/validate.go
return fmt.Errorf("required field is not set: capabilities")
} else {
for _, cap := range manifest.Capabilities {
if !slices.Contains(webui.SupportedCapabilities(), cap) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make SupportedCapabilities() a private method of the model manifest. This is now used beyond webui

Comment thread pkg/models/validate.go
return fmt.Errorf("required field is not set: environment")
}

return nil

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validate Layout

Comment thread pkg/runtimes/validate.go
return fmt.Errorf("required field is not set: components")
}

return nil

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validate Layout

if err == nil {
t.Fatal("Empty yaml should fail")
}
t.Log(err)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this just produce noise in verbose test logs. It should only print if there is something unexpected.

Same in several tests, also in models package.

}

if !allManifestsValid {
return fmt.Errorf("not all manifests are valid")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DE013 / CLI Copy and Tone of Voice:

Suggested change
return fmt.Errorf("some manifests are invalid")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants