diff --git a/examples/replacement-provides.yaml b/examples/replacement-provides.yaml new file mode 100644 index 000000000..7518ea125 --- /dev/null +++ b/examples/replacement-provides.yaml @@ -0,0 +1,13 @@ +package: + name: replacement-provides + version: 0.0.1 + description: example using a replacement in provides + dependencies: + provides: + - replacement-provides-version=${{package.version}} + - replacement-provides-foo=${{vars.foo}} + - replacement-provides-bar=${{vars.bar}} + +vars: + foo: FOO + bar: BAR diff --git a/pkg/config/config.go b/pkg/config/config.go index 62d622a7b..d422fb02d 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -23,6 +23,7 @@ import ( "path/filepath" "regexp" "sort" + "strconv" "strings" apko_types "chainguard.dev/apko/pkg/build/types" @@ -33,6 +34,7 @@ import ( "gopkg.in/yaml.v3" "chainguard.dev/melange/pkg/logger" + "chainguard.dev/melange/pkg/util" ) type Scriptlets struct { @@ -115,6 +117,27 @@ func (p Package) PackageURL(distro string) string { ) } +func (c *Configuration) applySubstitutionsForProvides() error { + nw := buildConfigMap(c) + for i, prov := range c.Package.Dependencies.Provides { + var err error + c.Package.Dependencies.Provides[i], err = util.MutateStringFromMap(nw, prov) + if err != nil { + return fmt.Errorf("failed to apply replacement to provides %q: %w", prov, err) + } + } + for _, sp := range c.Subpackages { + for i, prov := range sp.Dependencies.Provides { + var err error + sp.Dependencies.Provides[i], err = util.MutateStringFromMap(nw, prov) + if err != nil { + return fmt.Errorf("failed to apply replacement to provides %q: %w", prov, err) + } + } + } + return nil +} + type Copyright struct { // Optional: The license paths, typically '*' Paths []string `yaml:"paths,omitempty"` @@ -447,9 +470,10 @@ func detectCommit(dirPath string, logger apko_log.Logger) string { // buildConfigMap builds a map used to prepare a replacer for variable substitution. func buildConfigMap(cfg *Configuration) map[string]string { out := map[string]string{ - "${{package.name}}": cfg.Package.Name, - "${{package.version}}": cfg.Package.Version, - "${{package.description}}": cfg.Package.Description, + SubstitutionPackageName: cfg.Package.Name, + SubstitutionPackageVersion: cfg.Package.Version, + SubstitutionPackageDescription: cfg.Package.Description, + SubstitutionPackageEpoch: strconv.FormatUint(cfg.Package.Epoch, 10), } for k, v := range cfg.Vars { @@ -675,6 +699,10 @@ func ParseConfiguration(configurationFilePath string, opts ...ConfigurationParsi cfg.Subpackages = subpackages + if err := cfg.applySubstitutionsForProvides(); err != nil { + return nil, err + } + // Finally, validate the configuration we ended up with before returning it for use downstream. if err = cfg.validate(); err != nil { return nil, fmt.Errorf("validating configuration: %w", err) diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go new file mode 100644 index 000000000..3b2cb8410 --- /dev/null +++ b/pkg/config/config_test.go @@ -0,0 +1,53 @@ +package config + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" +) + +func Test_applySubstitutionsInProvides(t *testing.T) { + fp := filepath.Join(os.TempDir(), "melange-test-applySubstitutionsInProvides") + if err := os.WriteFile(fp, []byte(` +package: + name: replacement-provides + version: 0.0.1 + description: example using a replacement in provides + dependencies: + provides: + - replacement-provides-version=${{package.version}} + - replacement-provides-foo=${{vars.foo}} + - replacement-provides-bar=${{vars.bar}} + +vars: + foo: FOO + bar: BAR + +subpackages: + - name: subpackage + dependencies: + provides: + - subpackage-version=${{package.version}} + - subpackage-foo=${{vars.foo}} + - subpackage-bar=${{vars.bar}} +`), 0644); err != nil { + t.Fatal(err) + } + cfg, err := ParseConfiguration(fp) + if err != nil { + t.Fatalf("failed to parse configuration: %s", err) + } + require.Equal(t, []string{ + "replacement-provides-version=0.0.1", + "replacement-provides-foo=FOO", + "replacement-provides-bar=BAR", + }, cfg.Package.Dependencies.Provides) + + require.Equal(t, []string{ + "subpackage-version=0.0.1", + "subpackage-foo=FOO", + "subpackage-bar=BAR", + }, cfg.Subpackages[0].Dependencies.Provides) +} diff --git a/pkg/config/vars.go b/pkg/config/vars.go index 35c594dc3..50a7d800d 100644 --- a/pkg/config/vars.go +++ b/pkg/config/vars.go @@ -27,6 +27,7 @@ const ( SubstitutionPackageName = "${{package.name}}" SubstitutionPackageVersion = "${{package.version}}" SubstitutionPackageEpoch = "${{package.epoch}}" + SubstitutionPackageDescription = "${{package.description}}" SubstitutionTargetsDestdir = "${{targets.destdir}}" SubstitutionSubPkgDir = "${{targets.subpkgdir}}" SubstitutionHostTripletGnu = "${{host.triplet.gnu}}"