Skip to content

Align integration template path validation with Fleet#1122

Merged
teresaromero merged 7 commits intoelastic:mainfrom
teresaromero:fix-template-paths-validation
Mar 27, 2026
Merged

Align integration template path validation with Fleet#1122
teresaromero merged 7 commits intoelastic:mainfrom
teresaromero:fix-template-paths-validation

Conversation

@teresaromero
Copy link
Copy Markdown
Contributor

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:

  • Supports template_paths and applies Fleet precedence (template_paths before template_path) for policy inputs[] and data stream streams[].
  • Uses the same stream default as EPM when neither field is set: effective template_path is stream.yml.hbs (see parseAndVerifyStreams — default assignment).
  • Validates every data stream stream under data_stream/<name>/agent/stream/ independently of whether policy templates declare template_path / template_paths, matching how Fleet still compiles compiled_stream per stream (_compilePackageStream).
  • Validates policy inputs[] templates under agent/input/ only when template_paths or template_path is present; otherwise no input-template filesystem check, matching optional compiled_input when those fields are absent (_compilePackagePolicyInput).
  • Clarifies errors (data stream vs policy input). Maps a missing agent/stream directory to the same “template not found” style outcome Fleet would hit when resolving assets.

Integration policy inputs are not given an input.yml.hbs default in Fleet’s manifest parser (parseAndVerifyInputs); this change does not add that default either.

Why is it important?

Composable integrations that use template_paths or bundle inputs were seeing incorrect or misleading validation: the previous logic ignored template_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

Related issues

Fleet behavior references (justification)

Behavior Kibana Fleet / EPM (pinned commit)
Stream default stream.yml.hbs when no template_paths / template_path parse.ts L508–L513
template_paths before template_path when compiling policy input package_policy.ts _compilePackagePolicyInput L3629–L3662
template_paths before template_path when compiling stream package_policy.ts _compilePackageStream L3803–L3846
Input templates only from agent/input/; stream templates from dataset agent/stream/ Same regions; no cross-fallback
No input.yml.hbs default on integration inputs[] at parse parse.ts parseAndVerifyInputs L620–L653
Tests: template_paths wins when both set package_policy.test.ts L2538+

- 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
@teresaromero teresaromero marked this pull request as ready for review March 24, 2026 14:13
@teresaromero teresaromero requested a review from a team as a code owner March 24, 2026 14:13
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 24, 2026

📝 Walkthrough

Walkthrough

YAML models now accept template_paths arrays in addition to template_path for policy inputs and per-stream entries. Policy-template-level validation was removed and replaced by per-input validation that checks each inputs[].template_paths entry (falling back to inputs[].template_path when empty). Data-stream manifests are fully validated per stream row: the template is resolved using stream-level template_pathstemplate_pathstream.yml.hbs, and the resolved files must exist under data_stream/<dsDir>/agent/stream (missing files return an errTemplateNotFound). A dataStreamManifestReadError wrapper classifies manifest read/parse failures. Validation error messages now reference the data stream name and stream input label. Tests and fixtures were updated to cover these behaviors.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • 🛠️ Update Documentation: Commit on current branch
  • 🛠️ Update Documentation: Create PR

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between 7e0bc13 and be01dbd.

📒 Files selected for processing (47)
  • code/go/internal/validator/semantic/validate_integration_policy_template_path.go
  • code/go/internal/validator/semantic/validate_integration_policy_template_path_test.go
  • code/go/pkg/validator/limits_test.go
  • code/go/pkg/validator/validator_test.go
  • spec/changelog.yml
  • test/packages/bad_agent_version_v3/data_stream/foo/agent/stream/stream.yml.hbs
  • test/packages/bad_agent_version_v3/data_stream/k8s_data_stream/agent/stream/stream.yml.hbs
  • test/packages/bad_agent_version_v3/data_stream/k8s_data_stream_no_definitions/agent/stream/stream.yml.hbs
  • test/packages/bad_agent_version_v3/data_stream/pe/agent/stream/stream.yml.hbs
  • test/packages/bad_agent_version_v3/data_stream/subobjects/agent/stream/stream.yml.hbs
  • test/packages/bad_datastream_package_old_version/data_stream/logs/agent/stream/stream.yml.hbs
  • test/packages/bad_deployer_system_benchmark/data_stream/alert/agent/stream/stream.yml.hbs
  • test/packages/bad_deployer_system_test/data_stream/foo/agent/stream/stream.yml.hbs
  • test/packages/bad_integration_hbs/data_stream/foo/agent/stream/stream.yml.hbs
  • test/packages/bad_integration_hbs_linked/data_stream/foo/agent/stream/stream.yml.hbs
  • test/packages/bad_integration_input_template_path/data_stream/datasets/manifest.yml
  • test/packages/bad_kibana_tag_duplicate/data_stream/log/agent/stream/stream.yml.hbs
  • test/packages/bad_migrate_from/data_stream/logs/agent/stream/stream.yml.hbs
  • test/packages/deprecated_integration_stream_var/data_stream/new_data_stream/agent/stream/stream.yml.hbs
  • test/packages/docs_extra_files/data_stream/pe/agent/stream/stream.yml.hbs
  • test/packages/expanded/data_stream/foo/agent/stream/stream.yml.hbs
  • test/packages/expanded/data_stream/pe/agent/stream/stream.yml.hbs
  • test/packages/good/data_stream/foo/agent/stream/stream.yml.hbs
  • test/packages/good/data_stream/k8s_data_stream/agent/stream/stream.yml.hbs
  • test/packages/good/data_stream/k8s_data_stream_no_definitions/agent/stream/stream.yml.hbs
  • test/packages/good/data_stream/pe/agent/stream/stream.yml.hbs
  • test/packages/good_deployer_system_benchmark/data_stream/alert/agent/stream/stream.yml.hbs
  • test/packages/good_integration_template_paths/data_stream/sample_stream/agent/stream/stream.yml.hbs
  • test/packages/good_migrate_from/data_stream/logs/agent/stream/stream.yml.hbs
  • test/packages/good_v2/data_stream/foo/agent/stream/stream.yml.hbs
  • test/packages/good_v2/data_stream/k8s_data_stream/agent/stream/stream.yml.hbs
  • test/packages/good_v2/data_stream/k8s_data_stream_no_definitions/agent/stream/stream.yml.hbs
  • test/packages/good_v2/data_stream/pe/agent/stream/stream.yml.hbs
  • test/packages/good_v3/data_stream/foo/agent/stream/stream.yml.hbs
  • test/packages/good_v3/data_stream/k8s_data_stream/agent/stream/stream.yml.hbs
  • test/packages/good_v3/data_stream/k8s_data_stream_no_definitions/agent/stream/stream.yml.hbs
  • test/packages/good_v3/data_stream/pe/agent/stream/stream.yml.hbs
  • test/packages/good_v3/data_stream/subobjects/agent/stream/stream.yml.hbs
  • test/packages/good_var_groups/data_stream/findings/agent/stream/stream.yml.hbs
  • test/packages/input_groups/data_stream/ec2_logs/agent/stream/stream.yml.hbs
  • test/packages/input_groups_bad_data_stream/data_stream/ec2_logs/agent/stream/stream.yml.hbs
  • test/packages/missing_image_files/data_stream/pe/agent/stream/stream.yml.hbs
  • test/packages/missing_pipeline_dashes/data_stream/foo/agent/stream/stream.yml.hbs
  • test/packages/missing_required_fields/data_stream/foo/agent/stream/stream.yml.hbs
  • test/packages/with_links/data_stream/k8s_data_stream/agent/stream/stream.yml.hbs
  • test/packages/with_links/data_stream/k8s_data_stream_no_definitions/agent/stream/stream.yml.hbs
  • test/packages/with_links/data_stream/pe/agent/stream/stream.yml.hbs

…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
Comment on lines +145 to +148
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))
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Instead of the index of the stream, I think it could be added the stream title. According to the spec, that field is mandatory:

Suggested change
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"`
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

i've used the streams input key instead. thnks

title: Sample logs
description: Collect sample logs
template_path: missing.yml.hbs
template_path: stream.yml.hbs
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Would it be failing this package also without updating the template path value here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

@teresaromero
Copy link
Copy Markdown
Contributor Author

/test

Copy link
Copy Markdown
Contributor

@mrodm mrodm left a comment

Choose a reason for hiding this comment

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

LGTM
But before merging, please trigger a test of this change in the integrations repository via test integrations

@teresaromero
Copy link
Copy Markdown
Contributor Author

test integrations

@elastic-vault-github-plugin-prod
Copy link
Copy Markdown

Created or updated PR in integrations repository to test this version. Check elastic/integrations#18073

mrodm
mrodm previously approved these changes Mar 27, 2026
Copy link
Copy Markdown
Contributor

@mrodm mrodm left a comment

Choose a reason for hiding this comment

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

LGTM!

Just added some suggestions for tests, to ensure that the full error message is validated with require.Contains.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between 193981e and f70e11d.

📒 Files selected for processing (1)
  • code/go/internal/validator/semantic/validate_integration_policy_template_path_test.go

Comment on lines +75 to +256
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)
})
Copy link
Copy Markdown

@coderabbitai coderabbitai bot Mar 27, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

i will address this on a followup pr

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

good!

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 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

Copy link
Copy Markdown
Member

@jsoriano jsoriano left a comment

Choose a reason for hiding this comment

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

Thanks for adjusting the code. I think we should test this with integrations to avoid breaking changes, but we will also need to do this in #1127, so maybe it is not worth to do it here.

@teresaromero
Copy link
Copy Markdown
Contributor Author

Thanks for adjusting the code. I think we should test this with integrations to avoid breaking changes, but we will also need to do this in #1127, so maybe it is not worth to do it here.

i launched a test yesterday #1122 (comment) 👍🏻

@jsoriano
Copy link
Copy Markdown
Member

Thanks for adjusting the code. I think we should test this with integrations to avoid breaking changes, but we will also need to do this in #1127, so maybe it is not worth to do it here.

i launched a test yesterday #1122 (comment) 👍🏻

Perfect then!

@teresaromero teresaromero enabled auto-merge (squash) March 27, 2026 10:25
@teresaromero teresaromero merged commit b4aa42a into elastic:main Mar 27, 2026
4 checks passed
@elasticmachine
Copy link
Copy Markdown

💚 Build Succeeded

History

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.

4 participants