diff --git a/changelog/fragments/bundle-scorecard-input-dir.yaml b/changelog/fragments/bundle-scorecard-input-dir.yaml new file mode 100644 index 00000000000..615eab88b24 --- /dev/null +++ b/changelog/fragments/bundle-scorecard-input-dir.yaml @@ -0,0 +1,9 @@ +entries: + - description: > + Fixed `generate bundle` so that bundle metadata (`bundle.Dockerfile` and + `annotations.yaml`) references the scorecard config when the manifests are read + with `--input-dir`. Previously the config was written to the output directory + but looked up in the input directory, so the scorecard labels and `COPY` line + were omitted. + kind: bugfix + breaking: false diff --git a/internal/cmd/operator-sdk/generate/bundle/bundle.go b/internal/cmd/operator-sdk/generate/bundle/bundle.go index 36e2ca54760..8ac771891f3 100644 --- a/internal/cmd/operator-sdk/generate/bundle/bundle.go +++ b/internal/cmd/operator-sdk/generate/bundle/bundle.go @@ -291,20 +291,34 @@ func (c bundleCmd) runMetadata() error { } } - scorecardConfigPath := filepath.Join(bundleRoot, scorecard.DefaultConfigDir, scorecard.ConfigFileName) - bundleMetadata := bundleutil.BundleMetaData{ BundleDir: c.outputDir, PackageName: c.packageName, Channels: c.channels, DefaultChannel: c.defaultChannel, OtherLabels: metricsannotations.MakeBundleMetadataLabels(c.layout), - IsScoreConfigPresent: genutil.IsExist(scorecardConfigPath), + IsScoreConfigPresent: hasScorecardConfig(bundleRoot, c.outputDir), } return bundleMetadata.GenerateMetadata() } +// hasScorecardConfig reports whether a scorecard config exists in any of the given +// bundle directories. The config is written to the output directory by runManifests, +// which differs from the input directory when manifests are read from --input-dir, +// so both must be checked. +func hasScorecardConfig(dirs ...string) bool { + for _, dir := range dirs { + if dir == "" { + continue + } + if genutil.IsExist(filepath.Join(dir, scorecard.DefaultConfigDir, scorecard.ConfigFileName)) { + return true + } + } + return false +} + // pinImages is used to replace all image tags in the given manifests with digests func (c bundleCmd) pinImages(manifestPath string) error { manifests, err := pullspec.FromDirectory(manifestPath, nil) diff --git a/internal/cmd/operator-sdk/generate/bundle/bundle_test.go b/internal/cmd/operator-sdk/generate/bundle/bundle_test.go new file mode 100644 index 00000000000..b404696147c --- /dev/null +++ b/internal/cmd/operator-sdk/generate/bundle/bundle_test.go @@ -0,0 +1,48 @@ +// Copyright 2026 The Operator-SDK Authors +// +// 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 bundle + +import ( + "os" + "path/filepath" + "testing" + + "github.com/operator-framework/operator-sdk/internal/scorecard" +) + +func TestHasScorecardConfig(t *testing.T) { + inputDir := t.TempDir() + outputDir := t.TempDir() + + if hasScorecardConfig(inputDir, outputDir) { + t.Fatal("expected no scorecard config in empty directories") + } + + // The config is written to the output directory when manifests come from --input-dir. + cfgDir := filepath.Join(outputDir, filepath.FromSlash(scorecard.DefaultConfigDir)) + if err := os.MkdirAll(cfgDir, 0755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(cfgDir, scorecard.ConfigFileName), []byte("kind: Configuration\n"), 0666); err != nil { + t.Fatal(err) + } + + if !hasScorecardConfig(inputDir, outputDir) { + t.Fatal("expected scorecard config to be found in the output directory") + } + if hasScorecardConfig(inputDir, "") { + t.Fatal("expected no scorecard config when only the empty input directory is checked") + } +}