Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package melange for openSUSE:Factory checked in at 2026-06-01 18:04:00 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/melange (Old) and /work/SRC/openSUSE:Factory/.melange.new.1937 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "melange" Mon Jun 1 18:04:00 2026 rev:160 rq:1356266 version:0.51.0 Changes: -------- --- /work/SRC/openSUSE:Factory/melange/melange.changes 2026-05-29 18:10:04.241750527 +0200 +++ /work/SRC/openSUSE:Factory/.melange.new.1937/melange.changes 2026-06-01 18:05:52.422953088 +0200 @@ -1,0 +2,11 @@ +Mon Jun 01 05:19:49 UTC 2026 - Johannes Kastl <[email protected]> + +- Update to version 0.51.0: + * ci: allow production.cloudfront.docker.com in harden-runner + egress (#2552) + * feat: Add variable substitution for licenses (#2530) + * chore(config): also create and upload source tarballs of gitlab + repositories (#2511) + * go/build/v2: updated go/build pipeline (#2538) + +------------------------------------------------------------------- Old: ---- melange-0.50.8.obscpio New: ---- melange-0.51.0.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ melange.spec ++++++ --- /var/tmp/diff_new_pack.zwa95S/_old 2026-06-01 18:05:55.199068216 +0200 +++ /var/tmp/diff_new_pack.zwa95S/_new 2026-06-01 18:05:55.199068216 +0200 @@ -17,7 +17,7 @@ Name: melange -Version: 0.50.8 +Version: 0.51.0 Release: 0 Summary: Build APKs from source code License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.zwa95S/_old 2026-06-01 18:05:55.243070041 +0200 +++ /var/tmp/diff_new_pack.zwa95S/_new 2026-06-01 18:05:55.247070207 +0200 @@ -3,7 +3,7 @@ <param name="url">https://github.com/chainguard-dev/melange.git</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">refs/tags/v0.50.8</param> + <param name="revision">refs/tags/v0.51.0</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.zwa95S/_old 2026-06-01 18:05:55.271071203 +0200 +++ /var/tmp/diff_new_pack.zwa95S/_new 2026-06-01 18:05:55.275071369 +0200 @@ -3,6 +3,6 @@ <param name="url">https://github.com/chainguard-dev/melange</param> <param name="changesrevision">3f6115b820985d70ca3c93cdf8519c1b3b4cfe81</param></service><service name="tar_scm"> <param name="url">https://github.com/chainguard-dev/melange.git</param> - <param name="changesrevision">0bad31945544b24f4ed00b503fe8c4efdef621ba</param></service></servicedata> + <param name="changesrevision">cc2c81d6cef2c72df1e3f1f78d1408551844c42e</param></service></servicedata> (No newline at EOF) ++++++ melange-0.50.8.obscpio -> melange-0.51.0.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.50.8/docs/BUILD-FILE.md new/melange-0.51.0/docs/BUILD-FILE.md --- old/melange-0.50.8/docs/BUILD-FILE.md 2026-05-22 20:04:00.000000000 +0200 +++ new/melange-0.51.0/docs/BUILD-FILE.md 2026-05-29 22:26:45.000000000 +0200 @@ -94,17 +94,49 @@ TODO(vaikas): Saw something about riscv64. Does all include that? ### copyright -List of copyrights for this package. Each entry in the list consists of 3 -fields that define the scope (paths, and which license applies to it): +List of copyrights for this package. Each entry defines the scope (paths, +and which license applies to it) and may include the following fields: #### license The license for either the package or part of the package (if there are multiple entries). It is important to note that only packages with OSI-approved licenses can be included in Wolfi. You can check the relevant package info in the licenses page at [opensource.org](https://opensource.org/licenses/). +Supports variable substitution, which is useful for producing unique license references across version streamed packages. + #### paths [optional] -The license paths that this license applies to +File globs (relative to the package root) that this license applies to. +Defaults to `*` (the whole package). Use this when different parts of the +package ship under different licenses: +```yaml +copyright: + - license: Apache-2.0 + paths: + - "*" + - license: BSD-3-Clause + paths: + - "vendor/foo/**" +``` + +#### attestation [optional] +Free-form attribution text appended to the package's copyright notice (for +example, the upstream `NOTICE` contents): +```yaml +copyright: + - license: Apache-2.0 + attestation: | + Copyright 2024 Example Corp. + Licensed under the Apache License, Version 2.0. +``` -#### attestation -Attestations for this license. +#### license-path [optional] +Path (relative to the build workspace) to a file containing the license +text to embed in the SBOM. Required for non-SPDX `license` values. Supports +`${{package.*}}` and `${{vars.*}}` substitution. License must stay within +the workspace. + +#### detection-override [optional] +Overrides the result of automatic license detection for the file referenced +by `license-path`. Use this when the on-disk text is misidentified by the +classifier but the declared `license` is known to be correct. For example, saying that this entire package has license `PSF-2.0` ```yaml @@ -112,8 +144,24 @@ - license: PSF-2.0 ``` - TODO(vaikas): Add attestation example (only found TODO) - TODO(vaikas): Add paths example (only found *) +Another example using `license-path` with a versioned directory: +```yaml +copyright: + - license: CustomLicense + license-path: path/to/${{package.version}}/LICENSE +``` + +Variables in `license` are also substituted, which is helpful when the +SPDX identifier itself is derived from a `var-transforms` rule (e.g. +selecting `GPL-2.0-only` vs `GPL-3.0-only` based on the upstream version): +```yaml +vars: + license-version: "2.4" + +copyright: + - license: LicenseRef-SOME-LICENSE-${{vars.some-version}} + license-path: path/to/LICENSE +``` ### dependencies List of packages that this package depends on at runtime, but not during build diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.50.8/e2e-tests/git-dirty-detection-build.yaml new/melange-0.51.0/e2e-tests/git-dirty-detection-build.yaml --- old/melange-0.50.8/e2e-tests/git-dirty-detection-build.yaml 2026-05-22 20:04:00.000000000 +0200 +++ new/melange-0.51.0/e2e-tests/git-dirty-detection-build.yaml 2026-05-29 22:26:45.000000000 +0200 @@ -9,7 +9,7 @@ environment: contents: packages: - - go + - go-1.26 - git environment: CGO_ENABLED: "0" @@ -44,10 +44,9 @@ git commit -m "Initial commit" # Test 1: Clean repository should not have +dirty - - uses: go/build + - uses: go/build/v2 with: modroot: hello-app - packages: . output: git-clean-binary ignore-untracked-files: false @@ -68,10 +67,9 @@ cd hello-app echo "// Modified tracked file" >> main.go - - uses: go/build + - uses: go/build/v2 with: modroot: hello-app - packages: . output: git-modified-tracked-binary ignore-untracked-files: true @@ -93,10 +91,9 @@ git checkout -- main.go # Reset to clean echo "untracked content" > untracked.txt - - uses: go/build + - uses: go/build/v2 with: modroot: hello-app - packages: . output: git-untracked-not-ignored-binary ignore-untracked-files: false @@ -113,10 +110,9 @@ fi # Test 4: Same untracked file, ignore-untracked-files: true should NOT be +dirty - - uses: go/build + - uses: go/build/v2 with: modroot: hello-app - packages: . output: git-untracked-ignored-binary ignore-untracked-files: true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.50.8/e2e-tests/go-build-v2-build-test.yaml new/melange-0.51.0/e2e-tests/go-build-v2-build-test.yaml --- old/melange-0.50.8/e2e-tests/go-build-v2-build-test.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/melange-0.51.0/e2e-tests/go-build-v2-build-test.yaml 2026-05-29 22:26:45.000000000 +0200 @@ -0,0 +1,40 @@ +package: + name: go-build-v2-build-test + version: "1.3.1" + epoch: 0 + description: A simple, modern and secure encryption tool (and Go library) with small explicit keys, no config options, and UNIX-style composability. + copyright: + - license: BSD-3-Clause + +environment: + contents: + packages: + - go-1.26 + +pipeline: + - uses: git-checkout + with: + repository: https://github.com/FiloSottile/age.git + tag: v${{package.version}} + expected-commit: b8564adb6d58329b8a3e267360ca2b0abc4efe1d + + - uses: go/build/v2 + with: + packages: ./... + ldflags: -X main.Version=${{package.version}} + +test: + environment: + contents: + packages: + - busybox + - wolfi-baselayout + pipeline: + - runs: age --help + - runs: age-inspect --help + - runs: age-keygen --help + - runs: age-plugin-batchpass --help + - runs: age-plugin-pq --help + - runs: age-plugin-tag --help + - runs: age-plugin-tagpq --help + - runs: age-plugin-tagtest --help diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.50.8/pkg/build/pipelines/go/build/v2.yaml new/melange-0.51.0/pkg/build/pipelines/go/build/v2.yaml --- old/melange-0.50.8/pkg/build/pipelines/go/build/v2.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/melange-0.51.0/pkg/build/pipelines/go/build/v2.yaml 2026-05-29 22:26:45.000000000 +0200 @@ -0,0 +1,129 @@ +name: Run a build using the go compiler + +needs: + packages: + - busybox + - ca-certificates-bundle + +inputs: + packages: + description: | + List of space-separated packages to compile. Files can also be specified. + This value is passed as an argument to go build. All paths are relative + to inputs.modroot. Can be multiple packages. Defaults to "." build current package. To build all packages use "./...". + default: "." + + tags: + description: | + A comma-separated list of build tags to append to the go compiler + + toolchaintags: + description: | + A comma-separated list of default toolchain go build tags + default: "netgo,osusergo" + + output: + description: | + Filename to use when writing the binary. The final install location inside + the apk will be in prefix / install-dir / output. This is optional, by default the name of the package is used. + default: "" + + vendor: + description: | + If true, the go mod command will also update the vendor directory + default: "false" + + modroot: + default: "." + required: false + description: | + Top directory of the go module, this is where go.mod lives. Before buiding + the go pipeline wil cd into this directory. + + prefix: + description: | + Prefix to relocate binaries + default: usr + + ldflags: + description: | + List of [pattern=]arg to append to the go compiler with -ldflags + + strip: + description: | + Set of strip ldflags passed to the go compiler + # Note symbols tables are useful for cryptography audits and govulncheck + default: "-w" + + install-dir: + description: | + Directory where binaries will be installed + default: bin + + experiments: + description: | + A comma-separated list of Golang experiment names (ex: loopvar) to use + when building the binary. + default: "" + + extra-args: + description: | + A space-separated list of extra arguments to pass to the go build command. + default: "" + + amd64: + description: | + GOAMD64 microarchitecture level to use + default: "v2" + + arm64: + description: | + GOARM64 microarchitecture level to use + default: "v8.0" + + buildmode: + description: | + The -buildmode flag value. See "go help buildmode" for more information. + default: "default" + + ignore-untracked-files: + description: | + If true, we will provide a gitignore that ignore all untracked files. + default: "true" + +pipeline: + - runs: | + + # We sometimes have stray files in our build environment + # That we don't neccesarily want surfaced in the build version + if [ "${{inputs.ignore-untracked-files}}" = "true" ]; then + mkdir -p ~/.config/git/ + touch ~/.config/git/ignore + cp ~/.config/git/ignore ~/.config/git/ignore.bak + echo '**' > ~/.config/git/ignore + fi + + cd "${{inputs.modroot}}" + + # check if modroot is set correctly by checking go.mod file exist + if [ ! -e go.mod ]; then + echo "go.mod not found in ${{inputs.modroot}}" + exit 1 + fi + + LDFLAGS="${{inputs.strip}} ${{inputs.ldflags}}" + + BASE_PATH="${{inputs.prefix}}/${{inputs.install-dir}}/${{inputs.output}}" + + # Take advantage of melange's buid cache for downloaded modules + export GOMODCACHE=/var/cache/melange/gomodcache + + GOAMD64="${{inputs.amd64}}" GOARM64="${{inputs.arm64}}" GOEXPERIMENT="${{inputs.experiments}}" go build -o "${{targets.contextdir}}"/${BASE_PATH} -tags "${{inputs.toolchaintags}},${{inputs.tags}}" -ldflags "${LDFLAGS}" -trimpath -buildmode ${{inputs.buildmode}} ${{inputs.extra-args}} ${{inputs.packages}} + + # Clean up the gitignore file we created to avoid interfering with subsequent builds + if [ "${{inputs.ignore-untracked-files}}" = "true" ]; then + mv ~/.config/git/ignore.bak ~/.config/git/ignore + fi + + # Strip go binaries by default + - uses: strip diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.50.8/pkg/config/config.go new/melange-0.51.0/pkg/config/config.go --- old/melange-0.50.8/pkg/config/config.go 2026-05-22 20:04:00.000000000 +0200 +++ new/melange-0.51.0/pkg/config/config.go 2026-05-29 22:26:45.000000000 +0200 @@ -637,7 +637,7 @@ // getGitSBOMPackage creates an SBOM package for Git based repositories. // Returns nil package and nil error if the repository is not from a supported platform or // if neither a tag of expectedCommit is not provided -func getGitSBOMPackage(repo, tag, expectedCommit string, idComponents []string, licenseDeclared, hint, supplier string) (*sbom.Package, error) { +func getGitSBOMPackage(repo, tag, expectedCommit string, idComponents []string, licenseDeclared, supplier string) (*sbom.Package, error) { var repoType, namespace, name, ref string var downloadLocation string @@ -659,19 +659,11 @@ namespace, name, _ = strings.Cut(trimmedPath, "/") name = strings.TrimSuffix(name, ".git") - switch { - case repoURL.Host == "github.com": + switch repoURL.Host { + case "github.com": repoType = purl.TypeGithub downloadLocation = fmt.Sprintf("%s://github.com/%s/%s/archive/%s.tar.gz", repoURL.Scheme, namespace, name, ref) - case repoURL.Host == "gitlab.com": - repoType = purl.TypeGitlab - downloadLocation = fmt.Sprintf("%s://gitlab.com/%s/%s/-/archive/%s/%s.tar.gz", repoURL.Scheme, namespace, name, ref, ref) - - case strings.HasPrefix(repoURL.Host, "gitlab") || hint == "gitlab": - repoType = purl.TypeGeneric - downloadLocation = fmt.Sprintf("%s://%s/%s/%s/-/archive/%s/%s.tar.gz", repoURL.Scheme, repoURL.Host, namespace, name, ref, ref) - default: repoType = purl.TypeGeneric // We can't determine the namespace so use the supplier passed instead. @@ -707,7 +699,7 @@ var pu *purl.PackageURL switch repoType { - case purl.TypeGithub, purl.TypeGitlab: + case purl.TypeGithub: pu = &purl.PackageURL{ Type: repoType, Namespace: namespace, @@ -809,7 +801,6 @@ branch := with["branch"] tag := with["tag"] expectedCommit := with["expected-commit"] - hint := with["type-hint"] // We'll use all available data to ensure our SBOM's package ID is unique, even // when the same repo is git-checked out multiple times. @@ -828,7 +819,7 @@ idComponents = append(idComponents, uniqueID) } - gitPackage, err := getGitSBOMPackage(repo, tag, expectedCommit, idComponents, licenseDeclared, hint, supplier) + gitPackage, err := getGitSBOMPackage(repo, tag, expectedCommit, idComponents, licenseDeclared, supplier) if err != nil { return nil, err } else if gitPackage != nil { @@ -1526,6 +1517,23 @@ } } +func replaceCopyright(r *strings.Replacer, in []Copyright) []Copyright { + if in == nil { + return nil + } + out := make([]Copyright, len(in)) + for i, cp := range in { + out[i] = Copyright{ + Paths: replaceAll(r, cp.Paths), + Attestation: cp.Attestation, + License: r.Replace(cp.License), + LicensePath: r.Replace(cp.LicensePath), + DetectionOverride: cp.DetectionOverride, + } + } + return out +} + func replacePackage(r *strings.Replacer, commit string, in Package) Package { return Package{ Name: r.Replace(in.Name), @@ -1536,7 +1544,7 @@ URL: r.Replace(in.URL), Commit: replaceCommit(commit, in.Commit), TargetArchitecture: replaceAll(r, in.TargetArchitecture), - Copyright: in.Copyright, + Copyright: replaceCopyright(r, in.Copyright), Dependencies: replaceDependencies(r, in.Dependencies), Options: in.Options, Scriptlets: replaceScriptlets(r, in.Scriptlets), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.50.8/pkg/config/config_test.go new/melange-0.51.0/pkg/config/config_test.go --- old/melange-0.50.8/pkg/config/config_test.go 2026-05-22 20:04:00.000000000 +0200 +++ new/melange-0.51.0/pkg/config/config_test.go 2026-05-29 22:26:45.000000000 +0200 @@ -612,7 +612,6 @@ expectedCommit string idComponents []string licenseDeclared string - typeHint string supplier string expected *sbom.Package expectError bool @@ -624,7 +623,6 @@ expectedCommit: "", idComponents: []string{"test-id"}, licenseDeclared: "Apache-2.0", - typeHint: "", supplier: "wolfi", expected: &sbom.Package{ IDComponents: []string{"test-id"}, @@ -644,7 +642,6 @@ expectedCommit: "b5d6dcba7c835d8520b06c7f35e747d896c50b61", idComponents: []string{"test-id"}, licenseDeclared: "Apache-2.0", - typeHint: "", supplier: "wolfi", expected: &sbom.Package{ IDComponents: []string{"test-id"}, @@ -675,7 +672,6 @@ DownloadLocation: "https://github.com/chainguard-dev/melange/archive/b5d6dcba7c835d8520b06c7f35e747d896c50b61.tar.gz", }, expectError: false, - typeHint: "", }, { name: "gitlab.com repo with tag", @@ -684,16 +680,20 @@ expectedCommit: "", idComponents: []string{"test-id"}, licenseDeclared: "MIT", - typeHint: "", supplier: "wolfi", expected: &sbom.Package{ - IDComponents: []string{"test-id"}, - Name: "gitlab", - Version: "v15.11.0", - LicenseDeclared: "MIT", - Namespace: "gitlab-org", - PURL: &purl.PackageURL{Type: "gitlab", Namespace: "gitlab-org", Name: "gitlab", Version: "v15.11.0"}, - DownloadLocation: "https://gitlab.com/gitlab-org/gitlab/-/archive/v15.11.0/v15.11.0.tar.gz", + IDComponents: []string{"test-id"}, + Name: "gitlab-org/gitlab", + Version: "v15.11.0", + LicenseDeclared: "MIT", + Namespace: "wolfi", + PURL: &purl.PackageURL{ + Type: "generic", + Name: "gitlab-org/gitlab", + Version: "v15.11.0", + Qualifiers: purl.QualifiersFromMap(map[string]string{"vcs_url": "git+https://gitlab.com/gitlab-org/gitlab"}), + }, + DownloadLocation: "https://tarballs.cgr.dev/g/6fc8277be731c24196adfdfbbf4fab5a760941f1808efc8e2f37d1fae8b44ac3-v15.11.0.tar.gz", }, expectError: false, }, @@ -704,16 +704,20 @@ expectedCommit: "dd88f2ad62eeb81cf3562eb8284e3c97d3e94a8a", idComponents: []string{"test-id"}, licenseDeclared: "MIT", - typeHint: "", supplier: "wolfi", expected: &sbom.Package{ - IDComponents: []string{"test-id"}, - Name: "gitlab", - Version: "dd88f2ad62eeb81cf3562eb8284e3c97d3e94a8a", - LicenseDeclared: "MIT", - Namespace: "gitlab-org", - PURL: &purl.PackageURL{Type: "gitlab", Namespace: "gitlab-org", Name: "gitlab", Version: "dd88f2ad62eeb81cf3562eb8284e3c97d3e94a8a"}, - DownloadLocation: "https://gitlab.com/gitlab-org/gitlab/-/archive/dd88f2ad62eeb81cf3562eb8284e3c97d3e94a8a/dd88f2ad62eeb81cf3562eb8284e3c97d3e94a8a.tar.gz", + IDComponents: []string{"test-id"}, + Name: "gitlab-org/gitlab", + Version: "dd88f2ad62eeb81cf3562eb8284e3c97d3e94a8a", + LicenseDeclared: "MIT", + Namespace: "wolfi", + PURL: &purl.PackageURL{ + Type: "generic", + Name: "gitlab-org/gitlab", + Version: "dd88f2ad62eeb81cf3562eb8284e3c97d3e94a8a", + Qualifiers: purl.QualifiersFromMap(map[string]string{"vcs_url": "git+https://gitlab.com/gitlab-org/gitlab@dd88f2ad62eeb81cf3562eb8284e3c97d3e94a8a"}), + }, + DownloadLocation: "https://tarballs.cgr.dev/g/6fc8277be731c24196adfdfbbf4fab5a760941f1808efc8e2f37d1fae8b44ac3-dd88f2ad62eeb81cf3562eb8284e3c97d3e94a8a.tar.gz", }, expectError: false, }, @@ -724,16 +728,20 @@ expectedCommit: "dd88f2ad62eeb81cf3562eb8284e3c97d3e94a8a", idComponents: []string{"test-id"}, licenseDeclared: "MIT", - typeHint: "", supplier: "wolfi", expected: &sbom.Package{ - IDComponents: []string{"test-id"}, - Name: "gitlab", - Version: "v15.11.0", - LicenseDeclared: "MIT", - Namespace: "gitlab-org", - PURL: &purl.PackageURL{Type: "gitlab", Namespace: "gitlab-org", Name: "gitlab", Version: "v15.11.0"}, - DownloadLocation: "https://gitlab.com/gitlab-org/gitlab/-/archive/dd88f2ad62eeb81cf3562eb8284e3c97d3e94a8a/dd88f2ad62eeb81cf3562eb8284e3c97d3e94a8a.tar.gz", + IDComponents: []string{"test-id"}, + Name: "gitlab-org/gitlab", + Version: "v15.11.0", + LicenseDeclared: "MIT", + Namespace: "wolfi", + PURL: &purl.PackageURL{ + Type: "generic", + Name: "gitlab-org/gitlab", + Version: "v15.11.0", + Qualifiers: purl.QualifiersFromMap(map[string]string{"vcs_url": "git+https://gitlab.com/gitlab-org/gitlab@dd88f2ad62eeb81cf3562eb8284e3c97d3e94a8a"}), + }, + DownloadLocation: "https://tarballs.cgr.dev/g/6fc8277be731c24196adfdfbbf4fab5a760941f1808efc8e2f37d1fae8b44ac3-dd88f2ad62eeb81cf3562eb8284e3c97d3e94a8a.tar.gz", }, expectError: false, }, @@ -744,21 +752,20 @@ expectedCommit: "", idComponents: []string{"test-id"}, licenseDeclared: "BSD-3-Clause", - typeHint: "", supplier: "wolfi", expected: &sbom.Package{ IDComponents: []string{"test-id"}, - Name: "some-project", + Name: "some-org/some-project", Version: "v2.3.4", LicenseDeclared: "BSD-3-Clause", - Namespace: "some-org", + Namespace: "wolfi", PURL: &purl.PackageURL{ Type: "generic", - Name: "some-project", + Name: "some-org/some-project", Version: "v2.3.4", Qualifiers: purl.QualifiersFromMap(map[string]string{"vcs_url": "git+https://gitlab.foo.bar/some-org/some-project"}), }, - DownloadLocation: "https://gitlab.foo.bar/some-org/some-project/-/archive/v2.3.4/v2.3.4.tar.gz", + DownloadLocation: "https://tarballs.cgr.dev/s/4f7d9783d9d4ff72139aa427cb411b0a63413df38f9a586e0ea358366d5cacdd-v2.3.4.tar.gz", }, expectError: false, }, @@ -769,21 +776,20 @@ expectedCommit: "1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b", idComponents: []string{"test-id"}, licenseDeclared: "BSD-3-Clause", - typeHint: "", supplier: "wolfi", expected: &sbom.Package{ IDComponents: []string{"test-id"}, - Name: "some-project", + Name: "some-org/some-project", Version: "1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b", LicenseDeclared: "BSD-3-Clause", - Namespace: "some-org", + Namespace: "wolfi", PURL: &purl.PackageURL{ Type: "generic", - Name: "some-project", + Name: "some-org/some-project", Version: "1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b", Qualifiers: purl.QualifiersFromMap(map[string]string{"vcs_url": "git+https://gitlab.foo.bar/some-org/some-project@1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b"}), }, - DownloadLocation: "https://gitlab.foo.bar/some-org/some-project/-/archive/1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b/1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b.tar.gz", + DownloadLocation: "https://tarballs.cgr.dev/s/4f7d9783d9d4ff72139aa427cb411b0a63413df38f9a586e0ea358366d5cacdd-1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b.tar.gz", }, expectError: false, }, @@ -794,21 +800,20 @@ expectedCommit: "1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b", idComponents: []string{"test-id"}, licenseDeclared: "BSD-3-Clause", - typeHint: "", supplier: "wolfi", expected: &sbom.Package{ IDComponents: []string{"test-id"}, - Name: "some-project", + Name: "some-org/some-project", Version: "v2.3.4", LicenseDeclared: "BSD-3-Clause", - Namespace: "some-org", + Namespace: "wolfi", PURL: &purl.PackageURL{ Type: "generic", - Name: "some-project", + Name: "some-org/some-project", Version: "v2.3.4", Qualifiers: purl.QualifiersFromMap(map[string]string{"vcs_url": "git+https://gitlab.foo.bar/some-org/some-project@1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b"}), }, - DownloadLocation: "https://gitlab.foo.bar/some-org/some-project/-/archive/1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b/1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b.tar.gz", + DownloadLocation: "https://tarballs.cgr.dev/s/4f7d9783d9d4ff72139aa427cb411b0a63413df38f9a586e0ea358366d5cacdd-1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b.tar.gz", }, expectError: false, }, @@ -819,21 +824,20 @@ expectedCommit: "42b2b24fb8819f1ed3643aa9cf2a62f03868e3aa", idComponents: []string{"test-id"}, licenseDeclared: "BSD-3-Clause", - typeHint: "gitlab", supplier: "wolfi", expected: &sbom.Package{ IDComponents: []string{"test-id"}, - Name: "dav1d", + Name: "videolan/dav1d", Version: "1.5.1", LicenseDeclared: "BSD-3-Clause", - Namespace: "videolan", + Namespace: "wolfi", PURL: &purl.PackageURL{ Type: "generic", - Name: "dav1d", + Name: "videolan/dav1d", Version: "1.5.1", Qualifiers: purl.QualifiersFromMap(map[string]string{"vcs_url": "git+https://code.videolan.org/videolan/dav1d@42b2b24fb8819f1ed3643aa9cf2a62f03868e3aa"}), }, - DownloadLocation: "https://code.videolan.org/videolan/dav1d/-/archive/42b2b24fb8819f1ed3643aa9cf2a62f03868e3aa/42b2b24fb8819f1ed3643aa9cf2a62f03868e3aa.tar.gz", + DownloadLocation: "https://tarballs.cgr.dev/v/6e7cc395f547880c194fa2249f40c6ea5fc395f655cf033fa8d8e0641c94dd2c-42b2b24fb8819f1ed3643aa9cf2a62f03868e3aa.tar.gz", }, expectError: false, }, @@ -844,7 +848,6 @@ expectedCommit: "", idComponents: []string{"test-id"}, licenseDeclared: "LGPL-2.1", - typeHint: "", supplier: "wolfi", expected: &sbom.Package{ IDComponents: []string{"test-id"}, @@ -869,7 +872,6 @@ expectedCommit: "abcdef0123456789abcdef0123456789abcdef01", idComponents: []string{"test-id"}, licenseDeclared: "LGPL-2.1", - typeHint: "", supplier: "wolfi", expected: &sbom.Package{ IDComponents: []string{"test-id"}, @@ -894,7 +896,6 @@ expectedCommit: "abcdef0123456789abcdef0123456789abcdef01", idComponents: []string{"test-id"}, licenseDeclared: "LGPL-2.1", - typeHint: "", supplier: "wolfi", expected: &sbom.Package{ IDComponents: []string{"test-id"}, @@ -919,7 +920,6 @@ expectedCommit: "abcdef0123456789abcdef0123456789abcdef01", idComponents: []string{"test-id"}, licenseDeclared: "LGPL-2.1", - typeHint: "", supplier: "wolfi", expected: &sbom.Package{ IDComponents: []string{"test-id"}, @@ -941,7 +941,7 @@ for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - pkg, err := getGitSBOMPackage(tc.repo, tc.tag, tc.expectedCommit, tc.idComponents, tc.licenseDeclared, tc.typeHint, tc.supplier) + pkg, err := getGitSBOMPackage(tc.repo, tc.tag, tc.expectedCommit, tc.idComponents, tc.licenseDeclared, tc.supplier) if tc.expectError { require.Error(t, err) return @@ -2372,6 +2372,53 @@ }) } +// TestCopyrightVarSubstitution ensures that variable references in +// copyright[].license and copyright[].license-path are resolved during +// configuration parsing. +func TestCopyrightVarSubstitution(t *testing.T) { + ctx := slogtest.Context(t) + + fp := filepath.Join(os.TempDir(), "melange-test-copyright-vars") + if err := os.WriteFile(fp, []byte(` +package: + name: copyright-vars + version: 1.2.3 + epoch: 0 + description: test variable substitution in copyright fields + copyright: + - license: ${{vars.spdx-license}} + license-path: licenses/${{package.name}}-${{package.version}}/LICENSE + - license: LicenseRef-${{package.name}} + license-path: ${{vars.license-dir}}/NOTICE + - license: GPL-${{vars.short-version}}-only + license-path: licenses/${{vars.short-version}}/COPYING + +vars: + spdx-license: Apache-2.0 + license-dir: share/doc + +var-transforms: + - from: ${{package.version}} + match: ^(\d+)\.\d+\.\d+$ + replace: "$1.0" + to: short-version +`), 0o644); err != nil { + t.Fatal(err) + } + cfg, err := ParseConfiguration(ctx, fp) + if err != nil { + t.Fatalf("failed to parse configuration: %s", err) + } + + require.Len(t, cfg.Package.Copyright, 3) + require.Equal(t, "Apache-2.0", cfg.Package.Copyright[0].License) + require.Equal(t, "licenses/copyright-vars-1.2.3/LICENSE", cfg.Package.Copyright[0].LicensePath) + require.Equal(t, "LicenseRef-copyright-vars", cfg.Package.Copyright[1].License) + require.Equal(t, "share/doc/NOTICE", cfg.Package.Copyright[1].LicensePath) + require.Equal(t, "GPL-1.0-only", cfg.Package.Copyright[2].License) + require.Equal(t, "licenses/1.0/COPYING", cfg.Package.Copyright[2].LicensePath) +} + func TestLineNumbersInError(t *testing.T) { ctx := slogtest.Context(t) ++++++ melange.obsinfo ++++++ --- /var/tmp/diff_new_pack.zwa95S/_old 2026-06-01 18:05:57.223152158 +0200 +++ /var/tmp/diff_new_pack.zwa95S/_new 2026-06-01 18:05:57.231152490 +0200 @@ -1,5 +1,5 @@ name: melange -version: 0.50.8 -mtime: 1779473040 -commit: 0bad31945544b24f4ed00b503fe8c4efdef621ba +version: 0.51.0 +mtime: 1780086405 +commit: cc2c81d6cef2c72df1e3f1f78d1408551844c42e ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/melange/vendor.tar.gz /work/SRC/openSUSE:Factory/.melange.new.1937/vendor.tar.gz differ: char 13, line 1
