Align integration template path validation with Fleet#1122
Align integration template path validation with Fleet#1122teresaromero merged 7 commits intoelastic:mainfrom
Conversation
- Parse and validate template_paths before template_path on policy inputs and streams - Validate every data stream stream (default stream.yml.hbs) independent of policy inputs - Improve errors (policy input vs data stream); map missing agent/stream to template not found - Extend semantic and validator tests; add minimal stream fixtures to integration test packages Made-with: Cursor
📝 WalkthroughWalkthroughYAML models now accept ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@code/go/internal/validator/semantic/validate_integration_policy_template_path.go`:
- Around line 76-80: The error currently reports failures against the package
root manifest because manifestPath is always "manifest.yml"; change the error
paths to reference the specific data-stream manifest file by propagating the
per-data-stream manifest path from readDataStreamsManifests into subsequent
errors (e.g., use the map keys or returned manifest path for each data stream)
and call fsys.Path(<data-stream-manifest-path>) when constructing
specerrors.NewStructuredErrorf messages (instead of fsys.Path(manifestPath) or
file.Path()). Apply the same fix where similar errors are produced in the later
block around the code handling streams[].template_path (lines ~126-132),
ensuring all messages use fsys.Path(...) with the actual
data_stream/<name>/manifest.yml path.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ce8d9936-a0c4-470e-a4f7-8ee0697a3630
📒 Files selected for processing (47)
code/go/internal/validator/semantic/validate_integration_policy_template_path.gocode/go/internal/validator/semantic/validate_integration_policy_template_path_test.gocode/go/pkg/validator/limits_test.gocode/go/pkg/validator/validator_test.gospec/changelog.ymltest/packages/bad_agent_version_v3/data_stream/foo/agent/stream/stream.yml.hbstest/packages/bad_agent_version_v3/data_stream/k8s_data_stream/agent/stream/stream.yml.hbstest/packages/bad_agent_version_v3/data_stream/k8s_data_stream_no_definitions/agent/stream/stream.yml.hbstest/packages/bad_agent_version_v3/data_stream/pe/agent/stream/stream.yml.hbstest/packages/bad_agent_version_v3/data_stream/subobjects/agent/stream/stream.yml.hbstest/packages/bad_datastream_package_old_version/data_stream/logs/agent/stream/stream.yml.hbstest/packages/bad_deployer_system_benchmark/data_stream/alert/agent/stream/stream.yml.hbstest/packages/bad_deployer_system_test/data_stream/foo/agent/stream/stream.yml.hbstest/packages/bad_integration_hbs/data_stream/foo/agent/stream/stream.yml.hbstest/packages/bad_integration_hbs_linked/data_stream/foo/agent/stream/stream.yml.hbstest/packages/bad_integration_input_template_path/data_stream/datasets/manifest.ymltest/packages/bad_kibana_tag_duplicate/data_stream/log/agent/stream/stream.yml.hbstest/packages/bad_migrate_from/data_stream/logs/agent/stream/stream.yml.hbstest/packages/deprecated_integration_stream_var/data_stream/new_data_stream/agent/stream/stream.yml.hbstest/packages/docs_extra_files/data_stream/pe/agent/stream/stream.yml.hbstest/packages/expanded/data_stream/foo/agent/stream/stream.yml.hbstest/packages/expanded/data_stream/pe/agent/stream/stream.yml.hbstest/packages/good/data_stream/foo/agent/stream/stream.yml.hbstest/packages/good/data_stream/k8s_data_stream/agent/stream/stream.yml.hbstest/packages/good/data_stream/k8s_data_stream_no_definitions/agent/stream/stream.yml.hbstest/packages/good/data_stream/pe/agent/stream/stream.yml.hbstest/packages/good_deployer_system_benchmark/data_stream/alert/agent/stream/stream.yml.hbstest/packages/good_integration_template_paths/data_stream/sample_stream/agent/stream/stream.yml.hbstest/packages/good_migrate_from/data_stream/logs/agent/stream/stream.yml.hbstest/packages/good_v2/data_stream/foo/agent/stream/stream.yml.hbstest/packages/good_v2/data_stream/k8s_data_stream/agent/stream/stream.yml.hbstest/packages/good_v2/data_stream/k8s_data_stream_no_definitions/agent/stream/stream.yml.hbstest/packages/good_v2/data_stream/pe/agent/stream/stream.yml.hbstest/packages/good_v3/data_stream/foo/agent/stream/stream.yml.hbstest/packages/good_v3/data_stream/k8s_data_stream/agent/stream/stream.yml.hbstest/packages/good_v3/data_stream/k8s_data_stream_no_definitions/agent/stream/stream.yml.hbstest/packages/good_v3/data_stream/pe/agent/stream/stream.yml.hbstest/packages/good_v3/data_stream/subobjects/agent/stream/stream.yml.hbstest/packages/good_var_groups/data_stream/findings/agent/stream/stream.yml.hbstest/packages/input_groups/data_stream/ec2_logs/agent/stream/stream.yml.hbstest/packages/input_groups_bad_data_stream/data_stream/ec2_logs/agent/stream/stream.yml.hbstest/packages/missing_image_files/data_stream/pe/agent/stream/stream.yml.hbstest/packages/missing_pipeline_dashes/data_stream/foo/agent/stream/stream.yml.hbstest/packages/missing_required_fields/data_stream/foo/agent/stream/stream.yml.hbstest/packages/with_links/data_stream/k8s_data_stream/agent/stream/stream.yml.hbstest/packages/with_links/data_stream/k8s_data_stream_no_definitions/agent/stream/stream.yml.hbstest/packages/with_links/data_stream/pe/agent/stream/stream.yml.hbs
code/go/internal/validator/semantic/validate_integration_policy_template_path.go
Show resolved
Hide resolved
…ate-paths-validation
…errors Use fsys.Path(data_stream/<name>/manifest.yml) for read/parse failures from readDataStreamsManifests and for stream template_path validation errors instead of the package root manifest. Update validator tests to expect the correct file prefix for bad stream template packages. Made-with: Cursor
| errs = append(errs, specerrors.NewStructuredErrorf( | ||
| "file \"%s\" is invalid: data stream \"%s\" stream %d (input %q): %w", | ||
| fsys.Path(dsManifestPath), dsDir, i+1, streamInputLabel(s.Input), err)) | ||
| } |
There was a problem hiding this comment.
Instead of the index of the stream, I think it could be added the stream title. According to the spec, that field is mandatory:
| errs = append(errs, specerrors.NewStructuredErrorf( | |
| "file \"%s\" is invalid: data stream \"%s\" stream %d (input %q): %w", | |
| fsys.Path(dsManifestPath), dsDir, i+1, streamInputLabel(s.Input), err)) | |
| } | |
| errs = append(errs, specerrors.NewStructuredErrorf( | |
| "file \"%s\" is invalid: data stream \"%s\" stream %q (input %q): %w", | |
| fsys.Path(dsManifestPath), dsDir, s.Title, streamInputLabel(s.Input), err)) | |
| } |
IIUC for that it should be added title to the struct:
type stream struct {
Input string `yaml:"input"`
Title string `yaml:"title"`
TemplatePath string `yaml:"template_path"`
TemplatePaths []string `yaml:"template_paths"`
}There was a problem hiding this comment.
i've used the streams input key instead. thnks
code/go/internal/validator/semantic/validate_integration_policy_template_path.go
Outdated
Show resolved
Hide resolved
code/go/internal/validator/semantic/validate_integration_policy_template_path.go
Outdated
Show resolved
Hide resolved
| title: Sample logs | ||
| description: Collect sample logs | ||
| template_path: missing.yml.hbs | ||
| template_path: stream.yml.hbs |
There was a problem hiding this comment.
Would it be failing this package also without updating the template path value here?
There was a problem hiding this comment.
this test reprensets the invalid policy template input template_path. if i use a random template_path here template_path: missing.yml.hbs, then we will have 2 errors:
1. file "../../../../test/packages/bad_integration_input_template_path/data_stream/datasets/manifest.yml" is invalid: data stream "data_stream/datasets" stream input "logfile": template file not found
2. file "../../../../test/packages/bad_integration_input_template_path/manifest.yml" is invalid: policy template "sample": failed validation for policy input "logfile": template file not found
the one on the missing policy template, and the one on the data streams. They are not related so validation search for the given paths.
|
/test |
mrodm
left a comment
There was a problem hiding this comment.
LGTM
But before merging, please trigger a test of this change in the integrations repository via test integrations
|
test integrations |
|
Created or updated PR in integrations repository to test this version. Check elastic/integrations#18073 |
mrodm
left a comment
There was a problem hiding this comment.
LGTM!
Just added some suggestions for tests, to ensure that the full error message is validated with require.Contains.
code/go/internal/validator/semantic/validate_integration_policy_template_path_test.go
Outdated
Show resolved
Hide resolved
code/go/internal/validator/semantic/validate_integration_policy_template_path_test.go
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@code/go/internal/validator/semantic/validate_integration_policy_template_path_test.go`:
- Around line 75-256: The tests inside
TestValidateIntegrationPolicyTemplates_DataStreamStreams create complex
multi-file package layouts and should be moved to fixture-based validator tests;
extract the integration-level cases (those that create agent/input,
data_stream/*/manifest.yml, agent/stream templates and root manifest) into new
package fixtures under test/packages and add corresponding entries exercised by
the validator_test.go harness instead of using t.TempDir(), and keep only the
simple unit scenarios here that validate single-file or small-structure
behavior; locate references to the test function
TestValidateIntegrationPolicyTemplates_DataStreamStreams and the validator
function ValidateIntegrationPolicyTemplates to guide which cases to move and
update test/packages fixtures and validator_test.go to assert the same expected
errors/results.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 814bc7e4-a84c-4054-9df0-c51925ca8c99
📒 Files selected for processing (1)
code/go/internal/validator/semantic/validate_integration_policy_template_path_test.go
| func TestValidateIntegrationPolicyTemplates_DataStreamStreams(t *testing.T) { | ||
| t.Run("all stream templates valid", func(t *testing.T) { | ||
| d := t.TempDir() | ||
| writeMinimalIntegrationManifest(t, d) | ||
| err := os.MkdirAll(filepath.Join(d, "data_stream", "logs", "agent", "stream"), 0o755) | ||
| require.NoError(t, err) | ||
| err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "agent", "stream", "access.yml.hbs"), []byte(`x`), 0o644) | ||
| require.NoError(t, err) | ||
| err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "manifest.yml"), []byte(` | ||
| streams: | ||
| - input: nginx/access | ||
| title: A | ||
| description: d | ||
| template_path: access.yml.hbs | ||
| `), 0o644) | ||
| require.NoError(t, err) | ||
|
|
||
| errs := ValidateIntegrationPolicyTemplates(fspath.DirFS(d)) | ||
| require.Empty(t, errs) | ||
| }) | ||
|
|
||
| t.Run("input with non-existing template_path", func(t *testing.T) { | ||
| err = validateInputWithStreams(fspath.DirFS(d), "nginx/error", dsMap) | ||
| require.ErrorIs(t, errTemplateNotFound, err) | ||
| t.Run("missing stream template_path file", func(t *testing.T) { | ||
| d := t.TempDir() | ||
| writeMinimalIntegrationManifest(t, d) | ||
| err := os.MkdirAll(filepath.Join(d, "data_stream", "logs", "agent", "stream"), 0o755) | ||
| require.NoError(t, err) | ||
| err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "manifest.yml"), []byte(` | ||
| streams: | ||
| - input: nginx/access | ||
| title: A | ||
| description: d | ||
| template_path: access.yml.hbs | ||
| - input: nginx/error | ||
| title: E | ||
| description: d | ||
| template_path: error_stream.yml.hbs | ||
| `), 0o644) | ||
| require.NoError(t, err) | ||
| err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "agent", "stream", "access.yml.hbs"), []byte(`x`), 0o644) | ||
| require.NoError(t, err) | ||
|
|
||
| errs := ValidateIntegrationPolicyTemplates(fspath.DirFS(d)) | ||
| require.Len(t, errs, 1) | ||
| require.Contains(t, errs[0].Error(), `data stream "data_stream/logs" stream input "nginx/error": template file not found`) | ||
| }) | ||
|
|
||
| t.Run("valid input with default template_path", func(t *testing.T) { | ||
| err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "agent", "stream", "stream.yml.hbs"), []byte(`default stream template`), 0o644) | ||
| t.Run("default stream.yml.hbs when template_path omitted", func(t *testing.T) { | ||
| d := t.TempDir() | ||
| writeMinimalIntegrationManifest(t, d) | ||
| err := os.MkdirAll(filepath.Join(d, "data_stream", "logs", "agent", "stream"), 0o755) | ||
| require.NoError(t, err) | ||
| err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "agent", "stream", "stream.yml.hbs"), []byte(`x`), 0o644) | ||
| require.NoError(t, err) | ||
| defer os.Remove(filepath.Join(d, "data_stream", "logs", "agent", "stream", "stream.yml.hbs")) | ||
| err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "manifest.yml"), []byte(` | ||
| streams: | ||
| - input: nginx/other | ||
| title: O | ||
| description: d | ||
| `), 0o644) | ||
| require.NoError(t, err) | ||
|
|
||
| errs := ValidateIntegrationPolicyTemplates(fspath.DirFS(d)) | ||
| require.Empty(t, errs) | ||
| }) | ||
|
|
||
| err = validateInputWithStreams(fspath.DirFS(d), "nginx/other", dsMap) | ||
| t.Run("prefixed stream template filename", func(t *testing.T) { | ||
| d := t.TempDir() | ||
| writeMinimalIntegrationManifest(t, d) | ||
| err := os.MkdirAll(filepath.Join(d, "data_stream", "logs", "agent", "stream"), 0o755) | ||
| require.NoError(t, err) | ||
| err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "agent", "stream", "prefixstream.yml.hbs"), []byte(`x`), 0o644) | ||
| require.NoError(t, err) | ||
| err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "manifest.yml"), []byte(` | ||
| streams: | ||
| - input: prefix/stream | ||
| title: P | ||
| description: d | ||
| `), 0o644) | ||
| require.NoError(t, err) | ||
|
|
||
| errs := ValidateIntegrationPolicyTemplates(fspath.DirFS(d)) | ||
| require.Empty(t, errs) | ||
| }) | ||
|
|
||
| t.Run("valid input with default prefixed template_path", func(t *testing.T) { | ||
| err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "agent", "stream", "prefixstream.yml.hbs"), []byte(`access stream template`), 0o644) | ||
| t.Run("template_paths on stream Fleet precedence over template_path", func(t *testing.T) { | ||
| d := t.TempDir() | ||
| writeMinimalIntegrationManifest(t, d) | ||
| err := os.MkdirAll(filepath.Join(d, "data_stream", "logs", "agent", "stream"), 0o755) | ||
| require.NoError(t, err) | ||
| err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "agent", "stream", "a.yml.hbs"), []byte(`x`), 0o644) | ||
| require.NoError(t, err) | ||
| defer os.Remove(filepath.Join(d, "data_stream", "logs", "agent", "stream", "prefixstream.yml.hbs")) | ||
| err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "agent", "stream", "b.yml.hbs"), []byte(`y`), 0o644) | ||
| require.NoError(t, err) | ||
| err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "manifest.yml"), []byte(` | ||
| streams: | ||
| - input: custom | ||
| title: C | ||
| description: d | ||
| template_path: missing-only-this-would-matter.yml.hbs | ||
| template_paths: | ||
| - a.yml.hbs | ||
| - b.yml.hbs | ||
| `), 0o644) | ||
| require.NoError(t, err) | ||
|
|
||
| errs := ValidateIntegrationPolicyTemplates(fspath.DirFS(d)) | ||
| require.Empty(t, errs) | ||
| }) | ||
|
|
||
| err = validateInputWithStreams(fspath.DirFS(d), "prefix/stream", dsMap) | ||
| t.Run("policy input template_path set still validates stream templates", func(t *testing.T) { | ||
| d := t.TempDir() | ||
| err := os.MkdirAll(filepath.Join(d, "agent", "input"), 0o755) | ||
| require.NoError(t, err) | ||
| err = os.WriteFile(filepath.Join(d, "agent", "input", "input.yml.hbs"), []byte(`x`), 0o644) | ||
| require.NoError(t, err) | ||
| err = os.WriteFile(filepath.Join(d, "manifest.yml"), []byte(` | ||
| type: integration | ||
| policy_templates: | ||
| - name: pt | ||
| title: t | ||
| description: d | ||
| inputs: | ||
| - type: logfile | ||
| title: a | ||
| description: b | ||
| template_path: input.yml.hbs | ||
| `), 0o644) | ||
| require.NoError(t, err) | ||
| err = os.MkdirAll(filepath.Join(d, "data_stream", "logs", "agent", "stream"), 0o755) | ||
| require.NoError(t, err) | ||
| err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "manifest.yml"), []byte(` | ||
| streams: | ||
| - input: logfile | ||
| title: L | ||
| description: d | ||
| template_path: does-not-exist.yml.hbs | ||
| `), 0o644) | ||
| require.NoError(t, err) | ||
|
|
||
| errs := ValidateIntegrationPolicyTemplates(fspath.DirFS(d)) | ||
| require.Len(t, errs, 1) | ||
| require.Contains(t, errs[0].Error(), `data stream "data_stream/logs" stream input "logfile": template file not found`) | ||
| }) | ||
|
|
||
| t.Run("policy input template_paths", func(t *testing.T) { | ||
| d := t.TempDir() | ||
| err := os.MkdirAll(filepath.Join(d, "agent", "input"), 0o755) | ||
| require.NoError(t, err) | ||
| err = os.WriteFile(filepath.Join(d, "agent", "input", "t1.yml.hbs"), []byte(`x`), 0o644) | ||
| require.NoError(t, err) | ||
| err = os.WriteFile(filepath.Join(d, "agent", "input", "t2.yml.hbs"), []byte(`y`), 0o644) | ||
| require.NoError(t, err) | ||
| err = os.WriteFile(filepath.Join(d, "manifest.yml"), []byte(` | ||
| type: integration | ||
| policy_templates: | ||
| - name: pt | ||
| title: t | ||
| description: d | ||
| inputs: | ||
| - type: logfile | ||
| title: a | ||
| description: b | ||
| template_paths: | ||
| - t1.yml.hbs | ||
| - t2.yml.hbs | ||
| `), 0o644) | ||
| require.NoError(t, err) | ||
| err = os.MkdirAll(filepath.Join(d, "data_stream", "logs", "agent", "stream"), 0o755) | ||
| require.NoError(t, err) | ||
| err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "agent", "stream", "stream.yml.hbs"), []byte(`z`), 0o644) | ||
| require.NoError(t, err) | ||
| err = os.WriteFile(filepath.Join(d, "data_stream", "logs", "manifest.yml"), []byte(` | ||
| streams: | ||
| - input: logfile | ||
| title: L | ||
| description: d | ||
| `), 0o644) | ||
| require.NoError(t, err) | ||
|
|
||
| errs := ValidateIntegrationPolicyTemplates(fspath.DirFS(d)) | ||
| require.Empty(t, errs) | ||
| }) |
There was a problem hiding this comment.
Move these integration-level cases to fixture-based validator tests.
Line 75–Line 256 builds complex multi-file package layouts in t.TempDir() (root manifest, agent/input, data_stream/*/manifest.yml, agent/stream templates). These scenarios should be covered via test/packages/ and exercised from code/go/pkg/validator/validator_test.go to match the repository’s semantic-validator testing contract.
As per coding guidelines: “For simple validation rules checking a single file or simple structure, use unit tests with t.TempDir(); for complex scenarios with multiple files and directories, use test packages in test/packages/ tested via validator_test.go”.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@code/go/internal/validator/semantic/validate_integration_policy_template_path_test.go`
around lines 75 - 256, The tests inside
TestValidateIntegrationPolicyTemplates_DataStreamStreams create complex
multi-file package layouts and should be moved to fixture-based validator tests;
extract the integration-level cases (those that create agent/input,
data_stream/*/manifest.yml, agent/stream templates and root manifest) into new
package fixtures under test/packages and add corresponding entries exercised by
the validator_test.go harness instead of using t.TempDir(), and keep only the
simple unit scenarios here that validate single-file or small-structure
behavior; locate references to the test function
TestValidateIntegrationPolicyTemplates_DataStreamStreams and the validator
function ValidateIntegrationPolicyTemplates to guide which cases to move and
update test/packages fixtures and validator_test.go to assert the same expected
errors/results.
There was a problem hiding this comment.
i will address this on a followup pr
There was a problem hiding this comment.
@teresaromero, understood! Would you like me to open a GitHub issue to track the migration of the TestValidateIntegrationPolicyTemplates_DataStreamStreams complex cases to test/packages/ fixtures tested via validator_test.go?
🧠 Learnings used
Learnt from: CR
Repo: elastic/package-spec PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-27T17:36:33.014Z
Learning: Applies to code/go/internal/validator/semantic/*.go : For simple validation rules checking a single file or simple structure, use unit tests with t.TempDir(); for complex scenarios with multiple files and directories, use test packages in test/packages/ tested via validator_test.go
Learnt from: CR
Repo: elastic/package-spec PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-27T17:36:33.014Z
Learning: Applies to code/go/internal/validator/semantic/*.go : Use pkgpath.Files() to read manifests and file.Values() with JSONPath to query YAML in semantic validators
Learnt from: CR
Repo: elastic/package-spec PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-27T17:36:33.014Z
Learning: Applies to code/go/internal/validator/semantic/*.go : Use descriptive variable names in semantic validators: use full names like packageName (not pkgName), dataStreamManifests (not dsManifests), templateIndex (not ptIdx) for better readability
Learnt from: CR
Repo: elastic/package-spec PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-27T17:36:33.014Z
Learning: Applies to code/go/internal/validator/semantic/*.go : Split semantic validator functions into separate helper functions for file reading/parsing and validation logic
Learnt from: CR
Repo: elastic/package-spec PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-27T17:36:33.014Z
Learning: Applies to code/go/internal/validator/semantic/*.go : Use fsys.Path() for full package paths in error messages, not file.Path() which is relative within fsys, to ensure error messages match test framework expectations
Learnt from: CR
Repo: elastic/package-spec PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-27T17:36:33.014Z
Learning: Run go test ./code/go/internal first after any spec changes to validate spec files before running other tests
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
gh issue create \
--repo elastic/package-spec \
--title "Migrate TestValidateIntegrationPolicyTemplates_DataStreamStreams complex cases to test/packages/ fixtures" \
--assignee teresaromero \
--body "## Summary
The complex multi-file package layout test cases inside \`TestValidateIntegrationPolicyTemplates_DataStreamStreams\` in \`code/go/internal/validator/semantic/validate_integration_policy_template_path_test.go\` should be migrated to fixture-based validator tests under \`test/packages/\`, exercised via \`code/go/pkg/validator/validator_test.go\`.
## Background
Per the repository's semantic-validator testing contract (see \`AGENTS.md\`): for complex scenarios with multiple files and directories, use test packages in \`test/packages/\` tested via \`validator_test.go\`. Simple unit scenarios (single file or small structure) are appropriate for \`t.TempDir()\` unit tests.
The cases that build multi-file layouts (root manifest, \`agent/input\`, \`data_stream/*/manifest.yml\`, \`agent/stream\` templates) should be extracted into new package fixtures under \`test/packages/\` with corresponding entries in \`validator_test.go\` asserting the same expected errors/results.
## Context
- Identified during review of PR `#1122` (https://github.com/elastic/package-spec/pull/1122)
- Review comment: https://github.com/elastic/package-spec/pull/1122#discussion_r3000148813
- Requested by: `@teresaromero`
## Acceptance Criteria
- [ ] Extract integration-level cases from \`TestValidateIntegrationPolicyTemplates_DataStreamStreams\` into new \`test/packages/\` fixtures
- [ ] Add corresponding test assertions in \`validator_test.go\`
- [ ] Keep only simple/single-file unit scenarios in the semantic package test file
"
Length of output: 51
@teresaromero, done! I've opened elastic/package-spec#1128 to track the migration. It's assigned to you with the relevant context and acceptance criteria.
🧠 Learnings used
Learnt from: CR
Repo: elastic/package-spec PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-27T17:36:33.014Z
Learning: Applies to code/go/internal/validator/semantic/*.go : For simple validation rules checking a single file or simple structure, use unit tests with t.TempDir(); for complex scenarios with multiple files and directories, use test packages in test/packages/ tested via validator_test.go
Learnt from: CR
Repo: elastic/package-spec PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-27T17:36:33.014Z
Learning: Applies to code/go/internal/validator/semantic/*.go : Use pkgpath.Files() to read manifests and file.Values() with JSONPath to query YAML in semantic validators
Learnt from: CR
Repo: elastic/package-spec PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-27T17:36:33.014Z
Learning: Applies to code/go/internal/validator/semantic/*.go : Use descriptive variable names in semantic validators: use full names like packageName (not pkgName), dataStreamManifests (not dsManifests), templateIndex (not ptIdx) for better readability
Learnt from: CR
Repo: elastic/package-spec PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-27T17:36:33.014Z
Learning: Applies to code/go/internal/validator/semantic/*.go : Split semantic validator functions into separate helper functions for file reading/parsing and validation logic
Learnt from: CR
Repo: elastic/package-spec PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-27T17:36:33.014Z
Learning: Applies to code/go/internal/validator/semantic/*.go : Use fsys.Path() for full package paths in error messages, not file.Path() which is relative within fsys, to ensure error messages match test framework expectations
i launched a test yesterday #1122 (comment) 👍🏻 |
Perfect then! |
💚 Build Succeeded
History
|
Align integration template validation with Fleet
Fleet references below use pinned Kibana commit
27aca1a6(27aca1a63980cb0d9202a71076bc3b41d61a7aad).What does this PR do?
Aligns integration package semantic validation of agent templates with Fleet/EPM:
template_pathsand applies Fleet precedence (template_pathsbeforetemplate_path) for policyinputs[]and data streamstreams[].template_pathisstream.yml.hbs(seeparseAndVerifyStreams— default assignment).data_stream/<name>/agent/stream/independently of whether policy templates declaretemplate_path/template_paths, matching how Fleet still compilescompiled_streamper stream (_compilePackageStream).inputs[]templates underagent/input/only whentemplate_pathsortemplate_pathis present; otherwise no input-template filesystem check, matching optionalcompiled_inputwhen those fields are absent (_compilePackagePolicyInput).agent/streamdirectory to the same “template not found” style outcome Fleet would hit when resolving assets.Integration policy inputs are not given an
input.yml.hbsdefault in Fleet’s manifest parser (parseAndVerifyInputs); this change does not add that default either.Why is it important?
Composable integrations that use
template_pathsor bundle inputs were seeing incorrect or misleading validation: the previous logic ignoredtemplate_paths, coupled stream checks to policy inputs, and skipped stream validation when an input-level template was set. That diverged from Fleet, which resolves input and stream templates separately (same files as above). Surfaced while working on elastic-package#3277 (building integrations with dependencies / bundled inputs).Checklist
test/packagesthat prove my change is effective.spec/changelog.yml.Related issues
Fleet behavior references (justification)
stream.yml.hbswhen notemplate_paths/template_pathparse.tsL508–L513template_pathsbeforetemplate_pathwhen compiling policy inputpackage_policy.ts_compilePackagePolicyInputL3629–L3662template_pathsbeforetemplate_pathwhen compiling streampackage_policy.ts_compilePackageStreamL3803–L3846agent/input/; stream templates from datasetagent/stream/input.yml.hbsdefault on integrationinputs[]at parseparse.tsparseAndVerifyInputsL620–L653template_pathswins when both setpackage_policy.test.tsL2538+