Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package melange for openSUSE:Factory checked in at 2024-05-23 15:35:03 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/melange (Old) and /work/SRC/openSUSE:Factory/.melange.new.24587 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "melange" Thu May 23 15:35:03 2024 rev:21 rq:1175952 version:0.8.1 Changes: -------- --- /work/SRC/openSUSE:Factory/melange/melange.changes 2024-05-22 21:35:30.504631607 +0200 +++ /work/SRC/openSUSE:Factory/.melange.new.24587/melange.changes 2024-05-23 15:35:42.528592167 +0200 @@ -1,0 +2,16 @@ +Wed May 22 19:38:50 UTC 2024 - opensuse_buildserv...@ojkastl.de + +- Update to version 0.8.1: + * Avoid panic if no external config file ref + * Verify wolfictl scan works + * githuib: Fixup melange configfile test case + * sbom: add support for generic git-checkout urls + * github: add SBOM external ref checks + * sbom: add external ref ConfigFile itself + * lint + * externalRefs: implement github git-checkout + * Generate fully qualified and normalized PURLs straight away + * Style review comments + * sbom: include external refs for fetched tarballs in SPDX + +------------------------------------------------------------------- Old: ---- melange-0.8.0.obscpio New: ---- melange-0.8.1.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ melange.spec ++++++ --- /var/tmp/diff_new_pack.KykRfG/_old 2024-05-23 15:35:43.828639343 +0200 +++ /var/tmp/diff_new_pack.KykRfG/_new 2024-05-23 15:35:43.832639488 +0200 @@ -19,7 +19,7 @@ %define __arch_install_post export NO_BRP_STRIP_DEBUG=true Name: melange -Version: 0.8.0 +Version: 0.8.1 Release: 0 Summary: Build APKs from source code License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.KykRfG/_old 2024-05-23 15:35:43.864640649 +0200 +++ /var/tmp/diff_new_pack.KykRfG/_new 2024-05-23 15:35:43.868640794 +0200 @@ -3,7 +3,7 @@ <param name="url">https://github.com/chainguard-dev/melange</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">v0.8.0</param> + <param name="revision">v0.8.1</param> <param name="versionformat">@PARENT_TAG@</param> <param name="changesgenerate">enable</param> <param name="versionrewrite-pattern">v(.*)</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.KykRfG/_old 2024-05-23 15:35:43.896641810 +0200 +++ /var/tmp/diff_new_pack.KykRfG/_new 2024-05-23 15:35:43.900641955 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/chainguard-dev/melange</param> - <param name="changesrevision">c31490acbb5b4b672566aa042cc20e2e1feb23a5</param></service></servicedata> + <param name="changesrevision">fbf0b9becdcfb589edbe010326203d4618b684ab</param></service></servicedata> (No newline at EOF) ++++++ melange-0.8.0.obscpio -> melange-0.8.1.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.8.0/.github/workflows/e2e.yaml new/melange-0.8.1/.github/workflows/e2e.yaml --- old/melange-0.8.0/.github/workflows/e2e.yaml 2024-05-21 19:09:17.000000000 +0200 +++ new/melange-0.8.1/.github/workflows/e2e.yaml 2024-05-22 20:19:47.000000000 +0200 @@ -59,6 +59,36 @@ docker run --rm -v $(pwd)/sbom.json:/sbom.json --entrypoint "sh" cgr.dev/chainguard/wolfi-base -c "apk add spdx-tools-java && tools-java Verify /sbom.json" done + - name: Verify SBOM External Refs (git-checkout) + if: matrix.example == 'git-checkout.yaml' + run: | + set -euxo pipefail + tar -Oxf packages/x86_64/git-checkout*.apk var/lib/db/sbom > git-checkout.sbom.json + + # Verify APK ref + grep '"pkg:apk/unknown/git-checkout@v0.0.1-r0?arch=x86_64"' git-checkout.sbom.json + + # Verify github tag ref + grep '"pkg:github/puerco/hello.git@v0.0.1"' sbom.json git-checkout.sbom.json + + # Verify github sha ref + grep '"pkg:github/puerco/hello.git@a73c4feb284dc6ed1e5758740f717f99dcd4c9d7"' git-checkout.sbom.json + + # Verify generic git ref + grep '"pkg:generic/hello@v0.0.1?vcs_url=git%2Bhttps%3A%2F%2Fgitlab.com%2Fxnox%2Fhello.git%40a73c4feb284dc6ed1e5758740f717f99dcd4c9d7"' git-checkout.sbom.json + + # Verify ConfigFile ref + grep '"pkg:github/chainguard-dev/melange@${{github.sha}}#examples/git-checkout.yaml"' git-checkout.sbom.json + + - name: Verify SBOM External Refs (gnu-hello) + if: matrix.example == 'gnu-hello.yaml' + run: | + set -euxo pipefail + tar -Oxf packages/x86_64/hello-2*.apk var/lib/db/sbom > hello.sbom.json + + # Verify generic fetch ref + grep '"pkg:generic/hello@2.12?checksum=sha256%3Acf04af86dc085268c5f4470fbae49b18afbc221b78096aab842d934a76bad0ab\\u0026download_url=https%3A%2F%2Fftp.gnu.org%2Fgnu%2Fhello%2Fhello-2.12.tar.gz"' hello.sbom.json + - name: Check packages can be installed with apk run: | set -euxo pipefail diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.8.0/.github/workflows/wolfi-presubmit.yaml new/melange-0.8.1/.github/workflows/wolfi-presubmit.yaml --- old/melange-0.8.0/.github/workflows/wolfi-presubmit.yaml 2024-05-21 19:09:17.000000000 +0200 +++ new/melange-0.8.1/.github/workflows/wolfi-presubmit.yaml 2024-05-22 20:19:47.000000000 +0200 @@ -95,7 +95,23 @@ - run: | make SHELL="/bin/bash" MELANGE="sudo melange" package/${{ matrix.package }} - - run: | + - name: "Retrieve Wolfi advisory data" + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + with: + repository: "wolfi-dev/advisories" + path: "data/wolfi-advisories" + + # this need to point to main to always get the latest action + - uses: wolfi-dev/actions/install-wolfictl@main # main + + - name: Test installable and Scan for CVEs + run: | for f in packages/x86_64/${{ matrix.package }}-*.apk; do docker run --rm -v $(pwd):/work cgr.dev/chainguard/wolfi-base apk add --allow-untrusted /work/$f + wolfictl scan \ + --advisories-repo-dir 'data/wolfi-advisories' \ + --advisory-filter 'resolved' \ + --require-zero \ + $f \ + 2> /dev/null # The error message renders strangely on GitHub Actions, and the important information is already being sent to stdout. done diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.8.0/examples/git-checkout.yaml new/melange-0.8.1/examples/git-checkout.yaml --- old/melange-0.8.0/examples/git-checkout.yaml 2024-05-21 19:09:17.000000000 +0200 +++ new/melange-0.8.1/examples/git-checkout.yaml 2024-05-22 20:19:47.000000000 +0200 @@ -43,3 +43,10 @@ destination: tag-unpeeled tag: v0.0.1 expected-commit: fed9b28e2973bee65bcc503c6ab6522e8bfdd3d1 + + - uses: git-checkout + with: + repository: https://gitlab.com/xnox/hello.git + destination: gitlab + tag: v0.0.1 + expected-commit: a73c4feb284dc6ed1e5758740f717f99dcd4c9d7 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.8.0/pkg/build/build.go new/melange-0.8.1/pkg/build/build.go --- old/melange-0.8.0/pkg/build/build.go 2024-05-21 19:09:17.000000000 +0200 +++ new/melange-0.8.1/pkg/build/build.go 2024-05-22 20:19:47.000000000 +0200 @@ -35,6 +35,9 @@ "cloud.google.com/go/storage" "github.com/chainguard-dev/clog" apkofs "github.com/chainguard-dev/go-apk/pkg/fs" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/storage/filesystem" + purl "github.com/package-url/packageurl-go" "github.com/yookoala/realpath" "github.com/zealic/xignore" "go.opentelemetry.io/otel" @@ -473,6 +476,62 @@ return len(b.Configuration.Pipeline) == 0 } +// ConfigFileExternalRef calculates ExternalRef for the melange config +// file itself. +func (b *Build) ConfigFileExternalRef() (*purl.PackageURL, error) { + // configFile must exist + configpath, err := filepath.Abs(b.ConfigFile) + if err != nil { + return nil, err + } + // If not a git repository, skip + opt := &git.PlainOpenOptions{DetectDotGit: true} + r, err := git.PlainOpenWithOptions(configpath, opt) + if err != nil { + return nil, nil + } + // If no remote origin, skip (local git repo) + remote, err := r.Remote("origin") + if err != nil { + return nil, nil + } + repository := remote.Config().URLs[0] + // Only supports github-actions style https github checkouts + if !strings.HasPrefix(repository, "https://github.com/") { + return nil, nil + } + namespace, name, _ := strings.Cut(strings.TrimPrefix(repository, "https://github.com/"), "/") + + // Head must exist + ref, err := r.Head() + if err != nil { + return nil, err + } + version := ref.Hash() + + // Try to get configfile as subpath in the repository + s, ok := r.Storer.(*filesystem.Storage) + if !ok { + return nil, errors.New("Repository storage is not filesystem.Storage") + } + base := filepath.Dir(s.Filesystem().Root()) + subpath, err := filepath.Rel(base, configpath) + if err != nil { + return nil, err + } + newpurl := &purl.PackageURL{ + Type: "github", + Namespace: namespace, + Name: name, + Version: version.String(), + Subpath: subpath, + } + if err := newpurl.Normalize(); err != nil { + return nil, err + } + return newpurl, nil +} + func (b *Build) PopulateCache(ctx context.Context) error { log := clog.FromContext(ctx) ctx, span := otel.Tracer("melange").Start(ctx, "PopulateCache") @@ -646,6 +705,8 @@ b.GuestDir = guestDir } + var externalRefs []purl.PackageURL + log.Infof("evaluating pipelines for package requirements") for _, p := range b.Configuration.Pipeline { // fine to pass nil for config, since not running in container. @@ -654,6 +715,7 @@ if err := pctx.ApplyNeeds(ctx, &pb); err != nil { return fmt.Errorf("unable to apply pipeline requirements: %w", err) } + externalRefs = append(externalRefs, pctx.ExternalRefs...) } for _, spkg := range b.Configuration.Subpackages { @@ -665,10 +727,23 @@ if err := pctx.ApplyNeeds(ctx, &pb); err != nil { return fmt.Errorf("unable to apply pipeline requirements: %w", err) } + externalRefs = append(externalRefs, pctx.ExternalRefs...) } } pb.Subpackage = nil + configFileRef, err := b.ConfigFileExternalRef() + if err != nil { + return fmt.Errorf("failed to create ExternalRef for configfile: %w", err) + } + + if configFileRef != nil { + // In SPDX v3 there is dedicate field for this + // https://spdx.github.io/spdx-spec/v3.0/model/Build/Properties/configSourceUri/ + log.Infof("adding external ref %s for ConfigFile", configFileRef) + externalRefs = append(externalRefs, *configFileRef) + } + if b.EmptyWorkspace { log.Infof("empty workspace requested") } else { @@ -845,6 +920,7 @@ PackageVersion: fmt.Sprintf("%s-r%d", b.Configuration.Package.Version, b.Configuration.Package.Epoch), License: b.Configuration.Package.LicenseExpression(), LicensingInfos: licensinginfos, + ExternalRefs: externalRefs, Copyright: b.Configuration.Package.FullCopyright(), Namespace: namespace, Arch: b.Arch.ToAPK(), @@ -860,6 +936,7 @@ PackageVersion: fmt.Sprintf("%s-r%d", b.Configuration.Package.Version, b.Configuration.Package.Epoch), License: b.Configuration.Package.LicenseExpression(), LicensingInfos: licensinginfos, + ExternalRefs: externalRefs, Copyright: b.Configuration.Package.FullCopyright(), Namespace: namespace, Arch: b.Arch.ToAPK(), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.8.0/pkg/build/pipeline.go new/melange-0.8.1/pkg/build/pipeline.go --- old/melange-0.8.0/pkg/build/pipeline.go 2024-05-21 19:09:17.000000000 +0200 +++ new/melange-0.8.1/pkg/build/pipeline.go 2024-05-22 20:19:47.000000000 +0200 @@ -32,6 +32,7 @@ "gopkg.in/yaml.v3" apko_types "chainguard.dev/apko/pkg/build/types" + purl "github.com/package-url/packageurl-go" "chainguard.dev/melange/pkg/cond" "chainguard.dev/melange/pkg/config" @@ -46,6 +47,7 @@ // Ordered list of pipeline directories to search for pipelines PipelineDirs []string steps int + ExternalRefs []purl.PackageURL } func NewPipelineContext(p *config.Pipeline, environment *apko_types.ImageConfiguration, config *container.Config, pipelineDirs []string) *PipelineContext { @@ -513,6 +515,15 @@ return err } + externalRefs, err := pctx.computeExternalRefs(spctx) + if err != nil { + return err + } + if externalRefs != nil { + log.Infof(" adding external refs %s for pipeline %q", externalRefs, pctx.Identity()) + pctx.ExternalRefs = append(pctx.ExternalRefs, externalRefs...) + } + if err := spctx.ApplyNeeds(ctx, pb); err != nil { return err } @@ -531,6 +542,82 @@ return nil } +// computeExternalRefs generates PURLs for subpipelines +func (pctx *PipelineContext) computeExternalRefs(spctx *PipelineContext) ([]purl.PackageURL, error) { + var purls []purl.PackageURL + var newpurl purl.PackageURL + + switch pctx.Pipeline.Uses { + case "fetch": + args := make(map[string]string) + args["download_url"] = spctx.Pipeline.With["${{inputs.uri}}"] + if len(spctx.Pipeline.With["${{inputs.expected-sha256}}"]) > 0 { + args["checksum"] = "sha256:" + spctx.Pipeline.With["${{inputs.expected-sha256}}"] + } + if len(spctx.Pipeline.With["${{inputs.expected-sha512}}"]) > 0 { + args["checksum"] = "sha512:" + spctx.Pipeline.With["${{inputs.expected-sha512}}"] + } + newpurl = purl.PackageURL{ + Type: "generic", + Name: spctx.Pipeline.With["${{inputs.purl-name}}"], + Version: spctx.Pipeline.With["${{inputs.purl-version}}"], + Qualifiers: purl.QualifiersFromMap(args), + } + if err := newpurl.Normalize(); err != nil { + return nil, err + } + purls = append(purls, newpurl) + + case "git-checkout": + repository := spctx.Pipeline.With["${{inputs.repository}}"] + if strings.HasPrefix(repository, "https://github.com/") { + namespace, name, _ := strings.Cut(strings.TrimPrefix(repository, "https://github.com/"), "/") + versions := []string{ + spctx.Pipeline.With["${{inputs.tag}}"], + spctx.Pipeline.With["${{inputs.expected-commit}}"], + } + for _, version := range versions { + if version != "" { + newpurl = purl.PackageURL{ + Type: "github", + Namespace: namespace, + Name: name, + Version: version, + } + if err := newpurl.Normalize(); err != nil { + return nil, err + } + purls = append(purls, newpurl) + } + } + } else { + // Create nice looking package name, last component of uri, without .git + name := strings.TrimSuffix(filepath.Base(repository), ".git") + // Encode vcs_url with git+ prefix and @commit suffix + vcsUrl := "git+" + repository + if len(spctx.Pipeline.With["${{inputs.expected-commit}}"]) > 0 { + vcsUrl = vcsUrl + "@" + spctx.Pipeline.With["${{inputs.expected-commit}}"] + } + // Use tag as version + version := "" + if len(spctx.Pipeline.With["${{inputs.tag}}"]) > 0 { + version = spctx.Pipeline.With["${{inputs.tag}}"] + } + newpurl = purl.PackageURL{ + Type: "generic", + Name: name, + Version: version, + Qualifiers: purl.QualifiersFromMap(map[string]string{"vcs_url": vcsUrl}), + } + if err := newpurl.Normalize(); err != nil { + return nil, err + } + purls = append(purls, newpurl) + } + } + return purls, nil +} + // pipelineStepWorkDir returns the workdir for the current pipeline step. func (pctx *PipelineContext) pipelineStepWorkDir() (string, error) { if pctx.Pipeline.WorkDir == "" { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.8.0/pkg/build/pipelines/fetch.yaml new/melange-0.8.1/pkg/build/pipelines/fetch.yaml --- old/melange-0.8.0/pkg/build/pipelines/fetch.yaml 2024-05-21 19:09:17.000000000 +0200 +++ new/melange-0.8.1/pkg/build/pipelines/fetch.yaml 2024-05-22 20:19:47.000000000 +0200 @@ -23,6 +23,16 @@ description: | The expected SHA512 of the downloaded artifact. + purl-name: + description: | + package-URL (PURL) name for use in SPDX SBOM External References + default: ${{package.name}} + + purl-version: + description: | + package-URL (PURL) version for use in SPDX SBOM External References + default: ${{package.version}} + uri: description: | The URI to fetch as an artifact. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.8.0/pkg/sbom/bom.go new/melange-0.8.1/pkg/sbom/bom.go --- old/melange-0.8.0/pkg/sbom/bom.go 2024-05-21 19:09:17.000000000 +0200 +++ new/melange-0.8.1/pkg/sbom/bom.go 2024-05-22 20:19:47.000000000 +0200 @@ -17,7 +17,11 @@ // data) designed to be transcoded to specific formats. package sbom -import "fmt" +import ( + "fmt" + + purl "github.com/package-url/packageurl-go" +) type bom struct { Packages []pkg @@ -42,6 +46,7 @@ Arch string Checksums map[string]string Relationships []relationship + ExternalRefs []purl.PackageURL } func (p *pkg) ID() string { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.8.0/pkg/sbom/generator.go new/melange-0.8.1/pkg/sbom/generator.go --- old/melange-0.8.0/pkg/sbom/generator.go 2024-05-21 19:09:17.000000000 +0200 +++ new/melange-0.8.1/pkg/sbom/generator.go 2024-05-22 20:19:47.000000000 +0200 @@ -20,6 +20,7 @@ "time" "github.com/chainguard-dev/clog" + purl "github.com/package-url/packageurl-go" "go.opentelemetry.io/otel" ) @@ -33,6 +34,7 @@ PackageVersion string License string // Full SPDX license expression LicensingInfos map[string]string + ExternalRefs []purl.PackageURL Copyright string Namespace string Arch string diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.8.0/pkg/sbom/implementation.go new/melange-0.8.1/pkg/sbom/implementation.go --- old/melange-0.8.0/pkg/sbom/implementation.go 2024-05-21 19:09:17.000000000 +0200 +++ new/melange-0.8.1/pkg/sbom/implementation.go 2024-05-22 20:19:47.000000000 +0200 @@ -90,6 +90,7 @@ Relationships: []relationship{}, LicenseDeclared: spdx.NOASSERTION, LicenseConcluded: spdx.NOASSERTION, // remove when omitted upstream + ExternalRefs: spec.ExternalRefs, Copyright: spec.Copyright, Namespace: spec.Namespace, Arch: spec.Arch, @@ -149,6 +150,13 @@ Type: "purl", }) } + for _, purl := range p.ExternalRefs { + spdxPkg.ExternalRefs = append(spdxPkg.ExternalRefs, spdx.ExternalRef{ + Category: "PACKAGE_MANAGER", + Locator: purl.ToString(), + Type: "purl", + }) + } doc.Packages = append(doc.Packages, spdxPkg) ++++++ melange.obsinfo ++++++ --- /var/tmp/diff_new_pack.KykRfG/_old 2024-05-23 15:35:44.184652262 +0200 +++ /var/tmp/diff_new_pack.KykRfG/_new 2024-05-23 15:35:44.188652407 +0200 @@ -1,5 +1,5 @@ name: melange -version: 0.8.0 -mtime: 1716311357 -commit: c31490acbb5b4b672566aa042cc20e2e1feb23a5 +version: 0.8.1 +mtime: 1716401987 +commit: fbf0b9becdcfb589edbe010326203d4618b684ab ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/melange/vendor.tar.gz /work/SRC/openSUSE:Factory/.melange.new.24587/vendor.tar.gz differ: char 5, line 1