diff --git a/internal/modules/module.go b/internal/modules/module.go index e1a0d1a00..024df21b5 100644 --- a/internal/modules/module.go +++ b/internal/modules/module.go @@ -387,6 +387,7 @@ func mapModuleRules(linterSettings *pkg.LintersSettings, configSettings *config. rules.EnabledScriptRule.SetLevel(globalRules.EnabledScriptRule.Impact, fallbackImpact) rules.ReleaseLayoutRule.SetLevel(globalRules.ReleaseLayoutRule.Impact, fallbackImpact) rules.BundleLayoutRule.SetLevel(globalRules.BundleLayoutRule.Impact, fallbackImpact) + rules.HelmignoreCoverageRule.SetLevel(globalRules.HelmignoreCoverageRule.Impact, fallbackImpact) } // mapTemplatesRules configures Templates linter rules diff --git a/pkg/config.go b/pkg/config.go index a98025a7f..53a2fdefd 100644 --- a/pkg/config.go +++ b/pkg/config.go @@ -252,6 +252,7 @@ type ModuleLinterRules struct { EnabledScriptRule RuleConfig ReleaseLayoutRule RuleConfig BundleLayoutRule RuleConfig + HelmignoreCoverageRule RuleConfig } type OSSRuleSettings struct { Disable bool diff --git a/pkg/config/global/global.go b/pkg/config/global/global.go index a5b2fca78..7c329076c 100644 --- a/pkg/config/global/global.go +++ b/pkg/config/global/global.go @@ -132,6 +132,7 @@ type ModuleLinterRules struct { EnabledScriptRule RuleConfig `mapstructure:"enabled-script"` ReleaseLayoutRule RuleConfig `mapstructure:"release-layout"` BundleLayoutRule RuleConfig `mapstructure:"bundle-layout"` + HelmignoreCoverageRule RuleConfig `mapstructure:"helmignore-coverage"` } type TemplatesLinterConfig struct { diff --git a/pkg/linters/module/README.md b/pkg/linters/module/README.md index 6f1c22b82..cc442d312 100644 --- a/pkg/linters/module/README.md +++ b/pkg/linters/module/README.md @@ -8,7 +8,7 @@ The Module linter performs automated checks on Deckhouse modules to validate con ## Rules -The Module linter includes **9 validation rules**: +The Module linter includes the following validation rules: | Rule | Description | Configurable | |------|-------------|--------------| @@ -16,6 +16,7 @@ The Module linter includes **9 validation rules**: | [**oss**](#oss) | Validates open-source software attribution in `oss.yaml` | ✅ Yes | | [**conversions**](#conversions) | Validates OpenAPI conversion files and documentation | ✅ Yes | | [**helmignore**](#helmignore) | Validates `.helmignore` file presence and content | ✅ Yes | +| [**helmignore-coverage**](#helmignore-coverage) | Reports bundle-image files no `.helmignore` pattern excludes | ✅ Yes | | [**license**](#license) | Validates license headers in source files | ✅ Yes | | [**requirements**](#requirements) | Validates version requirements for features | ❌ No | | [**package-yaml**](#package-yaml) | Validates `package.yaml` metadata and new requirements schema | ✅ Yes | @@ -298,6 +299,25 @@ openapi/ # Chart.yaml ``` +**Scope:** `static` only. Whether the patterns cover what the module actually ships is +checked by [helmignore-coverage](#helmignore-coverage) against the built image. + +--- + +### Helmignore-coverage + +Reports entries in the bundle image root that no `.helmignore` pattern excludes — files Helm would therefore pull into the chart. + +**Purpose:** an uncovered non-chart file bloats every chart Helm packs from the module. This is the same check the `helmignore` rule used to run over the source tree, moved to the image: CI writes scratch files into a checkout, and each one read as an uncovered entry. The image holds only what werf's `includePaths` let through, so what it carries is what the module actually ships. + +**Checks:** +- ✅ Every package-root entry is matched by a `.helmignore` pattern +- ✅ Chart material needs no pattern and is exempt — `templates/`, `charts/`, `monitoring/`, `Chart.yaml`, `values.yaml`, plus the build-generated `images_digests.json`, which exists in no source tree + +Findings are reported at `warn`. Only the package root is walked, and only patterns the module wrote itself apply. + +**Scope:** `bundle` only. It needs a packed tree; running it over a source tree would report the scratch files CI writes and the build never ships. + --- ### License diff --git a/pkg/linters/module/module.go b/pkg/linters/module/module.go index 72d004b90..0fd1be188 100644 --- a/pkg/linters/module/module.go +++ b/pkg/linters/module/module.go @@ -81,6 +81,7 @@ func (l *Module) rules() []pkg.Rule { rules.NewEnabledScriptRule(m, level(cfg.Rules.EnabledScriptRule)), rules.NewReleaseLayoutRule(m, level(cfg.Rules.ReleaseLayoutRule)), rules.NewBundleLayoutRule(m, level(cfg.Rules.BundleLayoutRule)), + rules.NewHelmignoreCoverageRule(m, level(cfg.Rules.HelmignoreCoverageRule)), } } diff --git a/pkg/linters/module/rules/helmignore.go b/pkg/linters/module/rules/helmignore.go index 7b8ec4765..b00f4e06f 100644 --- a/pkg/linters/module/rules/helmignore.go +++ b/pkg/linters/module/rules/helmignore.go @@ -24,7 +24,6 @@ import ( "path/filepath" "strings" - "helm.sh/helm/v3/pkg/ignore" "k8s.io/utils/ptr" "github.com/deckhouse/dmt/pkg" @@ -41,19 +40,8 @@ const ( helmChartYaml = "Chart.yaml" ) -// moduleTemplateExclude is the set of files and directories that belong to -// the Deckhouse module and therefore should NOT be listed in .helmignore. -// These are either required by Helm for rendering or read by Deckhouse -// directly from the module filesystem. -var moduleTemplateExclude = map[string]bool{ - // Required by Helm for chart rendering - "templates": true, - "charts": true, - "monitoring": true, - "Chart.yaml": true, - "values.yaml": true, -} - +// HelmignoreRule validates the .helmignore file itself: that it exists, says +// something, and that its patterns are well formed. func NewHelmignoreRule(disable bool, m pkg.Module, errorList *errors.LintRuleErrorsList) *HelmignoreRule { return &HelmignoreRule{ @@ -134,75 +122,6 @@ func (r *HelmignoreRule) Check(_ context.Context) { // Validate patterns validatePatterns(lines, errorList) - - // Validate that all module root files/dirs (except module-template entries) - // are covered by .helmignore patterns. - r.checkModuleRootCoverage(modulePath, raw, errorList) -} - -// checkModuleRootCoverage scans the module root for all files and directories -// and verifies that everything except the standard module-template entries -// (templates/, charts/, Chart.yaml, values.yaml) is covered by a pattern in -// .helmignore. Helm's own ignore.Rules are used for proper pattern matching -// (wildcards, negation, directory-only rules, etc.). -func (r *HelmignoreRule) checkModuleRootCoverage(modulePath string, raw []byte, errorList *errors.LintRuleErrorsList) { - entries, err := os.ReadDir(modulePath) - if err != nil { - errorList.WithFilePath(helmignoreFile). - Errorf("Cannot read module directory: %s", err) - - return - } - - // Parse .helmignore using Helm's own rules engine. - rules, err := ignore.Parse(bytes.NewReader(raw)) - if err != nil { - errorList.WithFilePath(helmignoreFile). - Errorf("Cannot parse .helmignore: %s", err) - - return - } - - rules.AddDefaults() - - for _, entry := range entries { - name := entry.Name() - - // Skip .helmignore itself. - if name == helmignoreFile { - continue - } - - // Skip entries that are part of the standard module template and - // should NOT be ignored by Helm. - if moduleTemplateExclude[name] { - continue - } - - info, err := entry.Info() - if err != nil { - errorList.WithFilePath(helmignoreFile). - Errorf("Cannot stat '%s': %s", name, err) - - continue - } - - // Use Helm's ignore rules: if the entry is NOT ignored, it would be - // included in the Helm chart — which we don't want for non-template - // files/dirs. - if rules.Ignore(name, info) { - continue - } - - entryType := "File" - if entry.IsDir() { - entryType = "Directory" - name += "/" - } - - errorList.WithFilePath(helmignoreFile). - Warnf("%s '%s' is not listed in .helmignore", entryType, name) - } } func validatePatterns(patterns []string, errorList *errors.LintRuleErrorsList) { diff --git a/pkg/linters/module/rules/helmignore_coverage.go b/pkg/linters/module/rules/helmignore_coverage.go new file mode 100644 index 000000000..ecebc7044 --- /dev/null +++ b/pkg/linters/module/rules/helmignore_coverage.go @@ -0,0 +1,134 @@ +/* +Copyright 2026 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package rules + +import ( + "bytes" + "context" + "os" + "path/filepath" + + "helm.sh/helm/v3/pkg/ignore" + + "github.com/deckhouse/dmt/pkg" + "github.com/deckhouse/dmt/pkg/errors" +) + +const HelmignoreCoverageRuleName = "helmignore-coverage" + +// chartMaterial is the set of package-root entries Helm needs in the chart, so +// .helmignore must NOT exclude them and their being uncovered is not a finding. +var chartMaterial = map[string]bool{ + "templates": true, + "charts": true, + "monitoring": true, + "Chart.yaml": true, + "values.yaml": true, + + // Generated by the build and imported straight into the image. + "images_digests.json": true, +} + +// CoverageRule reports package-root entries the bundle image carries that no .helmignore +// pattern excludes — files Helm would therefore pull into the chart. +type CoverageRule struct { + pkg.RuleMeta + + module pkg.Module + errorList *errors.LintRuleErrorsList +} + +var _ pkg.Rule = (*CoverageRule)(nil) + +func NewHelmignoreCoverageRule(m pkg.Module, errorList *errors.LintRuleErrorsList) *CoverageRule { + return &CoverageRule{ + RuleMeta: pkg.RuleMeta{Name: HelmignoreCoverageRuleName}, + module: m, + errorList: errorList.WithRule(HelmignoreCoverageRuleName), + } +} + +func (r *CoverageRule) Check(_ context.Context) { + root := r.module.GetPath() + if root == "" { + return + } + + raw, err := os.ReadFile(filepath.Join(root, helmignoreFile)) + if err != nil { + // A missing .helmignore leaves nothing to compare the tree against. Its absence + // is bundle-layout's finding to report, not a second copy of it here. + if os.IsNotExist(err) { + return + } + + r.errorList.WithFilePath(helmignoreFile). + Errorf("Cannot read .helmignore file: %s", err) + + return + } + + rules, err := ignore.Parse(bytes.NewReader(raw)) + if err != nil { + r.errorList.WithFilePath(helmignoreFile). + Errorf("Cannot parse .helmignore: %s", err) + + return + } + + entries, err := os.ReadDir(root) + if err != nil { + r.errorList.WithFilePath(helmignoreFile). + Errorf("Cannot read package root: %s", err) + + return + } + + for _, entry := range entries { + r.checkEntry(rules, entry) + } +} + +// checkEntry reports one package-root entry that no pattern excludes. +func (r *CoverageRule) checkEntry(rules *ignore.Rules, entry os.DirEntry) { + name := entry.Name() + + if name == helmignoreFile || chartMaterial[name] { + return + } + + info, err := entry.Info() + if err != nil { + r.errorList.WithFilePath(name). + Errorf("Cannot stat '%s': %s", name, err) + + return + } + + if rules.Ignore(name, info) { + return + } + + kind := "File" + if entry.IsDir() { + kind = "Directory" + name += "/" + } + + r.errorList.WithFilePath(entry.Name()). + Warnf("%s '%s' is present in the bundle image and is not listed in .helmignore", kind, name) +} diff --git a/pkg/linters/module/rules/helmignore_coverage_test.go b/pkg/linters/module/rules/helmignore_coverage_test.go new file mode 100644 index 000000000..85b96c635 --- /dev/null +++ b/pkg/linters/module/rules/helmignore_coverage_test.go @@ -0,0 +1,151 @@ +/* +Copyright 2026 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package rules + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/deckhouse/dmt/pkg" + "github.com/deckhouse/dmt/pkg/errors" +) + +func TestCoverageRule(t *testing.T) { + tests := []struct { + name string + helmignore string // empty means no .helmignore at all + dirs []string + files []string + wantFilePaths []string + }{ + { + name: "no .helmignore is bundle-layout's finding, not ours", + helmignore: "", + dirs: []string{"images"}, + }, + { + name: "everything non-chart is covered", + helmignore: "hooks/\nopenapi/\ncrds/\ndocs/\nmodule.yaml\n", + dirs: []string{"hooks", "openapi", "crds", "docs", "templates", "charts"}, + files: []string{"module.yaml", "Chart.yaml"}, + }, + { + name: "an uncovered directory is a finding", + helmignore: "hooks/\n", + dirs: []string{"hooks", "images", "templates"}, + wantFilePaths: []string{"images"}, + }, + { + name: "an uncovered file is a finding", + helmignore: "hooks/\n", + dirs: []string{"hooks", "templates"}, + files: []string{"leftover.yaml", "werf.yaml"}, + wantFilePaths: []string{"leftover.yaml", "werf.yaml"}, + }, + { + name: "a directory covered without a trailing slash counts as covered", + helmignore: "hooks\n", + dirs: []string{"hooks", "templates"}, + }, + { + // helm applies a directory-only pattern to the entries inside the directory, + // not to the directory itself, so the wildcard leaves it uncovered. + name: "images/* does not cover the directory itself", + helmignore: "images/*\n", + dirs: []string{"images", "templates"}, + wantFilePaths: []string{"images"}, + }, + { + name: "a negated pattern does not count as covered", + helmignore: "!images/\n", + dirs: []string{"images", "templates"}, + wantFilePaths: []string{"images"}, + }, + { + name: "chart material needs no pattern", + helmignore: "hooks/\n", + dirs: []string{"templates", "charts", "monitoring"}, + files: []string{"Chart.yaml", "values.yaml", "images_digests.json"}, + }, + { + name: "helm rejects double-star, and we say so once", + helmignore: "images/**\n", + dirs: []string{"images"}, + wantFilePaths: []string{".helmignore"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + root := t.TempDir() + + for _, dir := range tt.dirs { + require.NoError(t, os.MkdirAll(filepath.Join(root, dir), 0750)) + } + + for _, file := range tt.files { + require.NoError(t, os.WriteFile(filepath.Join(root, file), []byte("x"), 0600)) + } + + if tt.helmignore != "" { + require.NoError(t, os.WriteFile(filepath.Join(root, ".helmignore"), []byte(tt.helmignore), 0600)) + } + + errorList := errors.NewLintRuleErrorsList() + NewHelmignoreCoverageRule(moduleAt(t, root), errorList).Check(t.Context()) + + got := make([]string, 0, len(errorList.GetErrors())) + for _, e := range errorList.GetErrors() { + got = append(got, e.FilePath) + } + + assert.ElementsMatch(t, tt.wantFilePaths, got) + }) + } +} + +// TestCoverageRuleReportsAtWarn pins the severity: an uncovered file bloats the chart, it +// does not break it, so the finding must not fail a build at the default level. +func TestCoverageRuleReportsAtWarn(t *testing.T) { + root := t.TempDir() + require.NoError(t, os.WriteFile(filepath.Join(root, ".helmignore"), []byte("hooks/\n"), 0600)) + require.NoError(t, os.WriteFile(filepath.Join(root, "leftover.yaml"), []byte("x"), 0600)) + + errorList := errors.NewLintRuleErrorsList() + NewHelmignoreCoverageRule(moduleAt(t, root), errorList).Check(t.Context()) + + errs := errorList.GetErrors() + require.Len(t, errs, 1) + assert.Equal(t, pkg.Warn, errs[0].Level) +} + +// TestCoverageRuleSkipsHelmignoreItself pins the entry a broad pattern would otherwise +// leave uncovered against itself: bundle-layout requires .helmignore in the package root, +// and no .helmignore lists itself. +func TestCoverageRuleSkipsHelmignoreItself(t *testing.T) { + root := t.TempDir() + require.NoError(t, os.WriteFile(filepath.Join(root, ".helmignore"), []byte("hooks/\n"), 0600)) + + errorList := errors.NewLintRuleErrorsList() + NewHelmignoreCoverageRule(moduleAt(t, root), errorList).Check(t.Context()) + + assert.Empty(t, errorList.GetErrors()) +} diff --git a/pkg/linters/module/rules/helmignore_test.go b/pkg/linters/module/rules/helmignore_test.go index 55db149ce..d426307a5 100644 --- a/pkg/linters/module/rules/helmignore_test.go +++ b/pkg/linters/module/rules/helmignore_test.go @@ -60,8 +60,6 @@ func TestHelmignoreRule_CheckHelmignore(t *testing.T) { name string createFile bool fileContent string - directories []string // directories to create in temp dir - files []string // files to create in temp dir expectedErrors []string }{ { @@ -91,7 +89,6 @@ func TestHelmignoreRule_CheckHelmignore(t *testing.T) { name: "valid .helmignore file", createFile: true, fileContent: "# Git\n.git/\n.gitignore\n# Documentation\nREADME.md\ndocs/\n# Development files\n*.md\n*.txt", - directories: []string{}, expectedErrors: []string{}, }, { @@ -138,125 +135,6 @@ func TestHelmignoreRule_CheckHelmignore(t *testing.T) { fileContent: "!Chart.yaml", expectedErrors: []string{}, }, - // --- Directory coverage tests --- - { - name: "all directories covered", - createFile: true, - fileContent: "hooks/\nimages/\nopenapi/\ndocs/", - directories: []string{"hooks", "images", "openapi", "docs", "templates"}, - expectedErrors: []string{}, - }, - { - name: "missing directory in helmignore", - createFile: true, - fileContent: "hooks/", - directories: []string{"hooks", "images"}, - expectedErrors: []string{ - "Directory 'images/' is not listed in .helmignore", - }, - }, - { - name: "multiple missing directories", - createFile: true, - fileContent: "hooks/", - directories: []string{"hooks", "images", "scripts"}, - expectedErrors: []string{ - "Directory 'images/' is not listed in .helmignore", - "Directory 'scripts/' is not listed in .helmignore", - }, - }, - { - name: "directory covered without trailing slash", - createFile: true, - fileContent: "hooks", - directories: []string{"hooks"}, - expectedErrors: []string{}, - }, - { - name: "directory covered with wildcard", - createFile: true, - fileContent: "images/*", - directories: []string{"images"}, - expectedErrors: []string{ - "Directory 'images/' is not listed in .helmignore", - }, - }, - { - name: "wildcard file covered", - createFile: true, - fileContent: "*.md", - directories: []string{}, - files: []string{"README.md", "CHANGELOG.md"}, - expectedErrors: []string{}, - }, - { - name: "file not covered", - createFile: true, - fileContent: "*.md", - directories: []string{}, - files: []string{"README.md", "go.mod"}, - expectedErrors: []string{ - "File 'go.mod' is not listed in .helmignore", - }, - }, - { - name: "double-wildcard is rejected by helm", - createFile: true, - fileContent: "images/**", - directories: []string{}, - expectedErrors: []string{ - "Cannot parse .helmignore: double-star (**) syntax is not supported", - }, - }, - { - name: "negated pattern does not count as covered", - createFile: true, - fileContent: "!images/", - directories: []string{"images"}, - expectedErrors: []string{ - "Directory 'images/' is not listed in .helmignore", - }, - }, - { - name: "templates directory is skipped", - createFile: true, - fileContent: "hooks/", - directories: []string{"hooks", "templates"}, - expectedErrors: []string{}, - }, - { - name: "charts directory is skipped", - createFile: true, - fileContent: "hooks/", - directories: []string{"hooks", "charts"}, - expectedErrors: []string{}, - }, - { - name: "monitoring directory is skipped (needed in chart)", - createFile: true, - fileContent: ".git/", - directories: []string{"monitoring"}, - expectedErrors: []string{}, - }, - { - name: "only helm rendering dirs are skipped", - createFile: true, - fileContent: ".git/", - directories: []string{"docs", "crds", "hooks", "monitoring", "openapi", "templates", "charts"}, - expectedErrors: []string{ - "Directory 'docs/' is not listed in .helmignore", - "Directory 'crds/' is not listed in .helmignore", - "Directory 'hooks/' is not listed in .helmignore", - "Directory 'openapi/' is not listed in .helmignore", - }, - }, - { - name: "empty module root only templates", - createFile: true, - fileContent: ".git/", - directories: []string{"templates"}, - expectedErrors: []string{}, - }, } for _, tt := range tests { @@ -264,18 +142,6 @@ func TestHelmignoreRule_CheckHelmignore(t *testing.T) { // Create temporary directory tempDir := t.TempDir() - // Create directories - for _, dir := range tt.directories { - err := os.MkdirAll(filepath.Join(tempDir, dir), 0750) - require.NoError(t, err) - } - - // Create files - for _, f := range tt.files { - err := os.WriteFile(filepath.Join(tempDir, f), []byte("test"), 0600) - require.NoError(t, err) - } - // Create .helmignore file if needed if tt.createFile { helmignorePath := filepath.Join(tempDir, ".helmignore") diff --git a/pkg/scopes/bundle.go b/pkg/scopes/bundle.go index 7ffc445c5..c60f782f6 100644 --- a/pkg/scopes/bundle.go +++ b/pkg/scopes/bundle.go @@ -40,6 +40,7 @@ import ( var bundleRules = map[string]set.Set{ moduleLinter.ID: set.New( modulerules.BundleLayoutRuleName, + modulerules.HelmignoreCoverageRuleName, ), docs.ID: set.New( docsrules.ReadmeRuleName, diff --git a/test/e2e/framework.go b/test/e2e/framework.go index dc580e77b..d53e78c71 100644 --- a/test/e2e/framework.go +++ b/test/e2e/framework.go @@ -48,10 +48,13 @@ import ( "github.com/deckhouse/dmt/internal/flags" "github.com/deckhouse/dmt/internal/manager" "github.com/deckhouse/dmt/internal/metrics" + "github.com/deckhouse/dmt/internal/modules" "github.com/deckhouse/dmt/internal/sources/static" "github.com/deckhouse/dmt/internal/test" "github.com/deckhouse/dmt/pkg" "github.com/deckhouse/dmt/pkg/config" + "github.com/deckhouse/dmt/pkg/errors" + "github.com/deckhouse/dmt/pkg/scopes" ) // Case kinds. A case either lints a module (KindLint, the default) or runs the @@ -60,6 +63,7 @@ const ( KindLint = "lint" KindConversions = "conversions" KindFix = "fix" + KindBundle = "bundle" ) // Finding declares one expected lint finding for a case. @@ -101,7 +105,9 @@ type CaseSpec struct { // Skip, when true, causes the test case to be skipped (t.Skip). Skip bool `yaml:"skip"` // Kind selects what to run against the module: "lint" (default) runs the - // full lint pipeline, "conversions" runs the `dmt test conversions` testers. + // full lint pipeline, "bundle" runs the bundle scope over the module + // directory as if it were an unpacked bundle image, "conversions" runs the + // `dmt test conversions` testers. // For conversions cases, findings are exposed with linter ID "conversions" // and ObjectID set to the test name, so the same expectations apply. Kind string `yaml:"kind"` @@ -158,6 +164,8 @@ func Run(kind, moduleDir string, matrix bool) ([]pkg.LinterError, error) { return RunConversions(moduleDir) case KindFix: return RunFix(moduleDir) + case KindBundle: + return LintBundle(moduleDir) case KindLint, "": return Lint(moduleDir, matrix) default: @@ -210,6 +218,78 @@ func Lint(moduleDir string, matrix bool) ([]pkg.LinterError, error) { return mng.GetErrors(), nil } +// LintBundle runs the bundle scope over a module directory, treating it as an image +// that has already been pulled and unpacked, and returns all findings. +// +// The registry path is deliberately not re-tested here: pulling and extracting have +// their own tests in internal/sources/remote, and a fake registry would only put a +// layer between the fixture and the rule under test. What this covers is the half a +// unit test cannot — that the bundle scope's rule table, its `remote.bundle` config +// section and its linters actually produce the finding. +func LintBundle(moduleDir string) ([]pkg.LinterError, error) { + tmpRoot, err := os.MkdirTemp("", "dmt-e2e-*") + if err != nil { + return nil, fmt.Errorf("create temp dir: %w", err) + } + defer os.RemoveAll(tmpRoot) + + target := filepath.Join(tmpRoot, filepath.Base(moduleDir)) + if err := copyDir(moduleDir, target); err != nil { + return nil, fmt.Errorf("copy module: %w", err) + } + + initLintFlagsOnce() + + cfg, err := config.NewDefaultRootConfig(target) + if err != nil { + return nil, fmt.Errorf("load config: %w", err) + } + + metrics.GetClient(target) + + mng := manager.New(cfg, bundleSource{dir: target}) + defer mng.Close() + + _ = mng.Run(context.Background()) + + return mng.GetErrors(), nil +} + +// bundleSource yields one bundle-scope target over a directory on disk. It stands in +// for internal/sources/remote, which reaches the same modules.NewRemoteModule through +// a registry pull. +type bundleSource struct { + dir string +} + +var _ manager.Source = bundleSource{} + +func (s bundleSource) ConfigDir() string { return s.dir } + +func (s bundleSource) Scopes() []scopes.Scope { return []scopes.Scope{scopes.Bundle} } + +func (s bundleSource) Close() {} + +func (s bundleSource) Targets( + _ context.Context, + cfg *config.RootConfig, + _ *errors.LintRuleErrorsList, + yield func(manager.Target) bool, +) error { + // The name comes from the image reference in a real remote run, so the directory + // name is the closest a fixture has. + name := filepath.Base(s.dir) + + yield(manager.Target{ + Module: modules.NewRemoteModule(s.dir, name, scopes.Bundle.Settings(cfg)), + Scope: scopes.Bundle, + ModuleID: name, + ObjectID: string(scopes.Bundle), + }) + + return nil +} + // RunFix runs the lint pipeline with --fix: the run collects findings with // deferred fixes, ApplyFixes patches module.yaml on disk, and GetErrors then // returns only the findings that remain unresolved (successfully fixed ones are diff --git a/test/e2e/testdata/module/helmignore-all-covered/expected.yaml b/test/e2e/testdata/module/helmignore-all-covered/expected.yaml deleted file mode 100644 index 410733d36..000000000 --- a/test/e2e/testdata/module/helmignore-all-covered/expected.yaml +++ /dev/null @@ -1,6 +0,0 @@ -description: > - .helmignore covers all module root directories (hooks/, openapi/, crds/, - docs/) except templates/ which is required by Helm. No helmignore errors - should be reported. -module: module -expectClean: true diff --git a/test/e2e/testdata/module/helmignore-all-covered/module/docs/README.md b/test/e2e/testdata/module/helmignore-all-covered/module/docs/README.md deleted file mode 100644 index 0ce8cd318..000000000 --- a/test/e2e/testdata/module/helmignore-all-covered/module/docs/README.md +++ /dev/null @@ -1 +0,0 @@ -# helmignore-covered diff --git a/test/e2e/testdata/module/helmignore-all-covered/module/docs/README_RU.md b/test/e2e/testdata/module/helmignore-all-covered/module/docs/README_RU.md deleted file mode 100644 index 0ce8cd318..000000000 --- a/test/e2e/testdata/module/helmignore-all-covered/module/docs/README_RU.md +++ /dev/null @@ -1 +0,0 @@ -# helmignore-covered diff --git a/test/e2e/testdata/module/helmignore-all-covered/module/module.yaml b/test/e2e/testdata/module/helmignore-all-covered/module/module.yaml deleted file mode 100644 index 01599e274..000000000 --- a/test/e2e/testdata/module/helmignore-all-covered/module/module.yaml +++ /dev/null @@ -1,9 +0,0 @@ -name: helmignore-covered -namespace: d8-helmignore-covered -stage: General Availability -weight: 910 -requirements: - deckhouse: ">= 1.68.0" -descriptions: - en: E2E test - all directories covered by .helmignore. - ru: E2E тест - все директории покрыты .helmignore. diff --git a/test/e2e/testdata/module/helmignore-all-covered/module/openapi/config-values.yaml b/test/e2e/testdata/module/helmignore-all-covered/module/openapi/config-values.yaml deleted file mode 100644 index 03b0d8bfe..000000000 --- a/test/e2e/testdata/module/helmignore-all-covered/module/openapi/config-values.yaml +++ /dev/null @@ -1,2 +0,0 @@ -type: object -properties: {} diff --git a/test/e2e/testdata/module/helmignore-all-covered/module/openapi/values.yaml b/test/e2e/testdata/module/helmignore-all-covered/module/openapi/values.yaml deleted file mode 100644 index 47180da56..000000000 --- a/test/e2e/testdata/module/helmignore-all-covered/module/openapi/values.yaml +++ /dev/null @@ -1,4 +0,0 @@ -x-extend: - schema: config-values.yaml -type: object -properties: {} diff --git a/test/e2e/testdata/module/helmignore-coverage-covered/expected.yaml b/test/e2e/testdata/module/helmignore-coverage-covered/expected.yaml new file mode 100644 index 000000000..77aeab16b --- /dev/null +++ b/test/e2e/testdata/module/helmignore-coverage-covered/expected.yaml @@ -0,0 +1,10 @@ +description: > + The same bundle image root with a .helmignore that names every non-chart entry + it carries. helmignore-coverage must report nothing. The sibling + helmignore-coverage-uncovered case proves the rule does fire when a pattern is + missing, so this expectPass is a live guard rather than a vacuous one. +kind: bundle +module: module +expectPass: + - linter: module + rule: helmignore-coverage diff --git a/test/e2e/testdata/module/helmignore-coverage-covered/module/.helmignore b/test/e2e/testdata/module/helmignore-coverage-covered/module/.helmignore new file mode 100644 index 000000000..dd8a758d6 --- /dev/null +++ b/test/e2e/testdata/module/helmignore-coverage-covered/module/.helmignore @@ -0,0 +1,5 @@ +hooks/ +openapi/ +docs/ +module.yaml +oss.yaml diff --git a/test/e2e/testdata/module/helmignore-coverage-covered/module/Chart.yaml b/test/e2e/testdata/module/helmignore-coverage-covered/module/Chart.yaml new file mode 100644 index 000000000..bbefc706f --- /dev/null +++ b/test/e2e/testdata/module/helmignore-coverage-covered/module/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v2 +name: e2e-bundle +version: 0.0.1 diff --git a/test/e2e/testdata/module/helmignore-all-covered/module/crds/.gitkeep b/test/e2e/testdata/module/helmignore-coverage-covered/module/charts/.gitkeep similarity index 100% rename from test/e2e/testdata/module/helmignore-all-covered/module/crds/.gitkeep rename to test/e2e/testdata/module/helmignore-coverage-covered/module/charts/.gitkeep diff --git a/test/e2e/testdata/module/helmignore-coverage-covered/module/docs/README.md b/test/e2e/testdata/module/helmignore-coverage-covered/module/docs/README.md new file mode 100644 index 000000000..3bbc9f1e3 --- /dev/null +++ b/test/e2e/testdata/module/helmignore-coverage-covered/module/docs/README.md @@ -0,0 +1 @@ +# e2e bundle fixture diff --git a/test/e2e/testdata/module/helmignore-all-covered/module/hooks/.gitkeep b/test/e2e/testdata/module/helmignore-coverage-covered/module/hooks/.gitkeep similarity index 100% rename from test/e2e/testdata/module/helmignore-all-covered/module/hooks/.gitkeep rename to test/e2e/testdata/module/helmignore-coverage-covered/module/hooks/.gitkeep diff --git a/test/e2e/testdata/module/helmignore-coverage-covered/module/images_digests.json b/test/e2e/testdata/module/helmignore-coverage-covered/module/images_digests.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/e2e/testdata/module/helmignore-coverage-covered/module/images_digests.json @@ -0,0 +1 @@ +{} diff --git a/test/e2e/testdata/module/helmignore-coverage-covered/module/module.yaml b/test/e2e/testdata/module/helmignore-coverage-covered/module/module.yaml new file mode 100644 index 000000000..0544ed3a4 --- /dev/null +++ b/test/e2e/testdata/module/helmignore-coverage-covered/module/module.yaml @@ -0,0 +1,5 @@ +name: e2e-bundle +stage: General Availability +descriptions: + en: e2e bundle fixture + ru: e2e bundle fixture diff --git a/test/e2e/testdata/module/helmignore-all-covered/module/templates/.gitkeep b/test/e2e/testdata/module/helmignore-coverage-covered/module/openapi/.gitkeep similarity index 100% rename from test/e2e/testdata/module/helmignore-all-covered/module/templates/.gitkeep rename to test/e2e/testdata/module/helmignore-coverage-covered/module/openapi/.gitkeep diff --git a/test/e2e/testdata/module/helmignore-coverage-covered/module/oss.yaml b/test/e2e/testdata/module/helmignore-coverage-covered/module/oss.yaml new file mode 100644 index 000000000..4d053f933 --- /dev/null +++ b/test/e2e/testdata/module/helmignore-coverage-covered/module/oss.yaml @@ -0,0 +1 @@ +projects: [] diff --git a/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/hooks/.gitkeep b/test/e2e/testdata/module/helmignore-coverage-covered/module/templates/.gitkeep similarity index 100% rename from test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/hooks/.gitkeep rename to test/e2e/testdata/module/helmignore-coverage-covered/module/templates/.gitkeep diff --git a/test/e2e/testdata/module/helmignore-coverage-uncovered/expected.yaml b/test/e2e/testdata/module/helmignore-coverage-uncovered/expected.yaml new file mode 100644 index 000000000..3f941cc0a --- /dev/null +++ b/test/e2e/testdata/module/helmignore-coverage-uncovered/expected.yaml @@ -0,0 +1,38 @@ +description: > + The bundle image root carries oss.yaml and leftover.yaml, and its .helmignore + names neither, so Helm would pull both into every chart packed from the module. + The bundle scope's helmignore-coverage rule must report each of them at warn. + Chart material (templates/, charts/, Chart.yaml) and the build-generated + images_digests.json need no pattern and must stay unreported, as must hooks/, + openapi/, docs/ and module.yaml, which the patterns do cover. docs/ is the + interesting one: bundle-layout requires it in the root, it is not chart + material, so it needs a pattern like any other shipped non-chart entry. +kind: bundle +module: module +expect: + - linter: module + rule: helmignore-coverage + level: warn + textContains: "File 'oss.yaml' is present in the bundle image and is not listed in .helmignore" + count: 1 + - linter: module + rule: helmignore-coverage + level: warn + textContains: "File 'leftover.yaml' is present in the bundle image and is not listed in .helmignore" + count: 1 +expectAbsent: + - linter: module + rule: helmignore-coverage + textContains: "images_digests.json" + - linter: module + rule: helmignore-coverage + textContains: "Chart.yaml" + - linter: module + rule: helmignore-coverage + textContains: "'templates/'" + - linter: module + rule: helmignore-coverage + textContains: "'hooks/'" + - linter: module + rule: helmignore-coverage + textContains: "module.yaml" diff --git a/test/e2e/testdata/module/helmignore-all-covered/module/.helmignore b/test/e2e/testdata/module/helmignore-coverage-uncovered/module/.helmignore similarity index 85% rename from test/e2e/testdata/module/helmignore-all-covered/module/.helmignore rename to test/e2e/testdata/module/helmignore-coverage-uncovered/module/.helmignore index b8193d44c..7ccdc1e99 100644 --- a/test/e2e/testdata/module/helmignore-all-covered/module/.helmignore +++ b/test/e2e/testdata/module/helmignore-coverage-uncovered/module/.helmignore @@ -1,5 +1,4 @@ hooks/ openapi/ -crds/ docs/ module.yaml diff --git a/test/e2e/testdata/module/helmignore-coverage-uncovered/module/Chart.yaml b/test/e2e/testdata/module/helmignore-coverage-uncovered/module/Chart.yaml new file mode 100644 index 000000000..bbefc706f --- /dev/null +++ b/test/e2e/testdata/module/helmignore-coverage-uncovered/module/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v2 +name: e2e-bundle +version: 0.0.1 diff --git a/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/templates/.gitkeep b/test/e2e/testdata/module/helmignore-coverage-uncovered/module/charts/.gitkeep similarity index 100% rename from test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/templates/.gitkeep rename to test/e2e/testdata/module/helmignore-coverage-uncovered/module/charts/.gitkeep diff --git a/test/e2e/testdata/module/helmignore-coverage-uncovered/module/docs/README.md b/test/e2e/testdata/module/helmignore-coverage-uncovered/module/docs/README.md new file mode 100644 index 000000000..3bbc9f1e3 --- /dev/null +++ b/test/e2e/testdata/module/helmignore-coverage-uncovered/module/docs/README.md @@ -0,0 +1 @@ +# e2e bundle fixture diff --git a/test/e2e/testdata/module/helmignore-missing-dir/module/hooks/.gitkeep b/test/e2e/testdata/module/helmignore-coverage-uncovered/module/hooks/.gitkeep similarity index 100% rename from test/e2e/testdata/module/helmignore-missing-dir/module/hooks/.gitkeep rename to test/e2e/testdata/module/helmignore-coverage-uncovered/module/hooks/.gitkeep diff --git a/test/e2e/testdata/module/helmignore-coverage-uncovered/module/images_digests.json b/test/e2e/testdata/module/helmignore-coverage-uncovered/module/images_digests.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/e2e/testdata/module/helmignore-coverage-uncovered/module/images_digests.json @@ -0,0 +1 @@ +{} diff --git a/test/e2e/testdata/module/helmignore-coverage-uncovered/module/leftover.yaml b/test/e2e/testdata/module/helmignore-coverage-uncovered/module/leftover.yaml new file mode 100644 index 000000000..412ac404f --- /dev/null +++ b/test/e2e/testdata/module/helmignore-coverage-uncovered/module/leftover.yaml @@ -0,0 +1 @@ +left: over diff --git a/test/e2e/testdata/module/helmignore-coverage-uncovered/module/module.yaml b/test/e2e/testdata/module/helmignore-coverage-uncovered/module/module.yaml new file mode 100644 index 000000000..0544ed3a4 --- /dev/null +++ b/test/e2e/testdata/module/helmignore-coverage-uncovered/module/module.yaml @@ -0,0 +1,5 @@ +name: e2e-bundle +stage: General Availability +descriptions: + en: e2e bundle fixture + ru: e2e bundle fixture diff --git a/test/e2e/testdata/module/helmignore-missing-dir/module/images/.gitkeep b/test/e2e/testdata/module/helmignore-coverage-uncovered/module/openapi/.gitkeep similarity index 100% rename from test/e2e/testdata/module/helmignore-missing-dir/module/images/.gitkeep rename to test/e2e/testdata/module/helmignore-coverage-uncovered/module/openapi/.gitkeep diff --git a/test/e2e/testdata/module/helmignore-coverage-uncovered/module/oss.yaml b/test/e2e/testdata/module/helmignore-coverage-uncovered/module/oss.yaml new file mode 100644 index 000000000..4d053f933 --- /dev/null +++ b/test/e2e/testdata/module/helmignore-coverage-uncovered/module/oss.yaml @@ -0,0 +1 @@ +projects: [] diff --git a/test/e2e/testdata/module/helmignore-missing-dir/module/templates/.gitkeep b/test/e2e/testdata/module/helmignore-coverage-uncovered/module/templates/.gitkeep similarity index 100% rename from test/e2e/testdata/module/helmignore-missing-dir/module/templates/.gitkeep rename to test/e2e/testdata/module/helmignore-coverage-uncovered/module/templates/.gitkeep diff --git a/test/e2e/testdata/module/helmignore-dir-covered-without-slash/expected.yaml b/test/e2e/testdata/module/helmignore-dir-covered-without-slash/expected.yaml deleted file mode 100644 index 187badaaf..000000000 --- a/test/e2e/testdata/module/helmignore-dir-covered-without-slash/expected.yaml +++ /dev/null @@ -1,6 +0,0 @@ -description: > - .helmignore lists directories without a trailing slash (hooks, openapi, docs). - The rule must recognise these patterns as covering the directories. - No errors expected. -module: module -expectClean: true diff --git a/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/.helmignore b/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/.helmignore deleted file mode 100644 index 1121ff813..000000000 --- a/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/.helmignore +++ /dev/null @@ -1,4 +0,0 @@ -hooks -openapi -docs -module.yaml diff --git a/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/docs/README.md b/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/docs/README.md deleted file mode 100644 index fef7cb349..000000000 --- a/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/docs/README.md +++ /dev/null @@ -1 +0,0 @@ -# helmignore-no-slash diff --git a/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/docs/README_RU.md b/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/docs/README_RU.md deleted file mode 100644 index fef7cb349..000000000 --- a/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/docs/README_RU.md +++ /dev/null @@ -1 +0,0 @@ -# helmignore-no-slash diff --git a/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/module.yaml b/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/module.yaml deleted file mode 100644 index 4d832427b..000000000 --- a/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/module.yaml +++ /dev/null @@ -1,9 +0,0 @@ -name: helmignore-no-slash -namespace: d8-helmignore-no-slash -stage: General Availability -weight: 910 -requirements: - deckhouse: ">= 1.68.0" -descriptions: - en: E2E test - directory covered in .helmignore without trailing slash. - ru: E2E тест - директория покрыта без завершающего слеша. diff --git a/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/openapi/config-values.yaml b/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/openapi/config-values.yaml deleted file mode 100644 index 03b0d8bfe..000000000 --- a/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/openapi/config-values.yaml +++ /dev/null @@ -1,2 +0,0 @@ -type: object -properties: {} diff --git a/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/openapi/values.yaml b/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/openapi/values.yaml deleted file mode 100644 index 47180da56..000000000 --- a/test/e2e/testdata/module/helmignore-dir-covered-without-slash/module/openapi/values.yaml +++ /dev/null @@ -1,4 +0,0 @@ -x-extend: - schema: config-values.yaml -type: object -properties: {} diff --git a/test/e2e/testdata/module/helmignore-missing-dir/expected.yaml b/test/e2e/testdata/module/helmignore-missing-dir/expected.yaml deleted file mode 100644 index 088b93169..000000000 --- a/test/e2e/testdata/module/helmignore-missing-dir/expected.yaml +++ /dev/null @@ -1,15 +0,0 @@ -description: > - .helmignore lists hooks/ and module.yaml but the module also has images/ - and openapi/ directories. The rule must report each uncovered directory. -module: module -expect: - - linter: module - rule: helmignore - level: warn - textContains: "Directory 'images/' is not listed in .helmignore" - count: 1 - - linter: module - rule: helmignore - level: warn - textContains: "Directory 'openapi/' is not listed in .helmignore" - count: 1 diff --git a/test/e2e/testdata/module/helmignore-missing-dir/module/.helmignore b/test/e2e/testdata/module/helmignore-missing-dir/module/.helmignore deleted file mode 100644 index f72055bf2..000000000 --- a/test/e2e/testdata/module/helmignore-missing-dir/module/.helmignore +++ /dev/null @@ -1,2 +0,0 @@ -hooks/ -module.yaml diff --git a/test/e2e/testdata/module/helmignore-missing-dir/module/module.yaml b/test/e2e/testdata/module/helmignore-missing-dir/module/module.yaml deleted file mode 100644 index 446056768..000000000 --- a/test/e2e/testdata/module/helmignore-missing-dir/module/module.yaml +++ /dev/null @@ -1,9 +0,0 @@ -name: helmignore-missing -namespace: d8-helmignore-missing -stage: General Availability -weight: 910 -requirements: - deckhouse: ">= 1.68.0" -descriptions: - en: E2E test - images/ directory missing from .helmignore. - ru: E2E тест - images/ директория отсутствует в .helmignore. diff --git a/test/e2e/testdata/module/helmignore-missing-dir/module/openapi/config-values.yaml b/test/e2e/testdata/module/helmignore-missing-dir/module/openapi/config-values.yaml deleted file mode 100644 index 03b0d8bfe..000000000 --- a/test/e2e/testdata/module/helmignore-missing-dir/module/openapi/config-values.yaml +++ /dev/null @@ -1,2 +0,0 @@ -type: object -properties: {} diff --git a/test/e2e/testdata/module/helmignore-missing-dir/module/openapi/values.yaml b/test/e2e/testdata/module/helmignore-missing-dir/module/openapi/values.yaml deleted file mode 100644 index 47180da56..000000000 --- a/test/e2e/testdata/module/helmignore-missing-dir/module/openapi/values.yaml +++ /dev/null @@ -1,4 +0,0 @@ -x-extend: - schema: config-values.yaml -type: object -properties: {} diff --git a/test/e2e/testdata/module/helmignore-multiple-missing/expected.yaml b/test/e2e/testdata/module/helmignore-multiple-missing/expected.yaml deleted file mode 100644 index d32459fb6..000000000 --- a/test/e2e/testdata/module/helmignore-multiple-missing/expected.yaml +++ /dev/null @@ -1,26 +0,0 @@ -description: > - .helmignore lists hooks/ and module.yaml but the module has images/, - docs/, openapi/, crds/ directories. templates/ and charts/ are skipped - (module-template). -module: module -expect: - - linter: module - rule: helmignore - level: warn - textContains: "Directory 'images/' is not listed in .helmignore" - count: 1 - - linter: module - rule: helmignore - level: warn - textContains: "Directory 'docs/' is not listed in .helmignore" - count: 1 - - linter: module - rule: helmignore - level: warn - textContains: "Directory 'openapi/' is not listed in .helmignore" - count: 1 - - linter: module - rule: helmignore - level: warn - textContains: "Directory 'crds/' is not listed in .helmignore" - count: 1 diff --git a/test/e2e/testdata/module/helmignore-multiple-missing/module/.helmignore b/test/e2e/testdata/module/helmignore-multiple-missing/module/.helmignore deleted file mode 100644 index f72055bf2..000000000 --- a/test/e2e/testdata/module/helmignore-multiple-missing/module/.helmignore +++ /dev/null @@ -1,2 +0,0 @@ -hooks/ -module.yaml diff --git a/test/e2e/testdata/module/helmignore-multiple-missing/module/charts/.gitkeep b/test/e2e/testdata/module/helmignore-multiple-missing/module/charts/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/e2e/testdata/module/helmignore-multiple-missing/module/crds/.gitkeep b/test/e2e/testdata/module/helmignore-multiple-missing/module/crds/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/e2e/testdata/module/helmignore-multiple-missing/module/docs/.gitkeep b/test/e2e/testdata/module/helmignore-multiple-missing/module/docs/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/e2e/testdata/module/helmignore-multiple-missing/module/hooks/.gitkeep b/test/e2e/testdata/module/helmignore-multiple-missing/module/hooks/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/e2e/testdata/module/helmignore-multiple-missing/module/images/.gitkeep b/test/e2e/testdata/module/helmignore-multiple-missing/module/images/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/e2e/testdata/module/helmignore-multiple-missing/module/module.yaml b/test/e2e/testdata/module/helmignore-multiple-missing/module/module.yaml deleted file mode 100644 index eef6e4b75..000000000 --- a/test/e2e/testdata/module/helmignore-multiple-missing/module/module.yaml +++ /dev/null @@ -1,9 +0,0 @@ -name: helmignore-multi-miss -namespace: d8-helmignore-multi-miss -stage: General Availability -weight: 910 -requirements: - deckhouse: ">= 1.68.0" -descriptions: - en: E2E test - multiple directories missing from .helmignore. - ru: E2E тест - несколько директорий не покрыты в .helmignore. diff --git a/test/e2e/testdata/module/helmignore-multiple-missing/module/openapi/config-values.yaml b/test/e2e/testdata/module/helmignore-multiple-missing/module/openapi/config-values.yaml deleted file mode 100644 index 03b0d8bfe..000000000 --- a/test/e2e/testdata/module/helmignore-multiple-missing/module/openapi/config-values.yaml +++ /dev/null @@ -1,2 +0,0 @@ -type: object -properties: {} diff --git a/test/e2e/testdata/module/helmignore-multiple-missing/module/openapi/values.yaml b/test/e2e/testdata/module/helmignore-multiple-missing/module/openapi/values.yaml deleted file mode 100644 index 47180da56..000000000 --- a/test/e2e/testdata/module/helmignore-multiple-missing/module/openapi/values.yaml +++ /dev/null @@ -1,4 +0,0 @@ -x-extend: - schema: config-values.yaml -type: object -properties: {} diff --git a/test/e2e/testdata/module/helmignore-multiple-missing/module/templates/.gitkeep b/test/e2e/testdata/module/helmignore-multiple-missing/module/templates/.gitkeep deleted file mode 100644 index e69de29bb..000000000