Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package melange for openSUSE:Factory checked 
in at 2025-07-09 17:28:21
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/melange (Old)
 and      /work/SRC/openSUSE:Factory/.melange.new.7373 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "melange"

Wed Jul  9 17:28:21 2025 rev:102 rq:1291375 version:0.29.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/melange/melange.changes  2025-07-06 
17:18:05.656236399 +0200
+++ /work/SRC/openSUSE:Factory/.melange.new.7373/melange.changes        
2025-07-09 17:29:32.330379380 +0200
@@ -1,0 +2,11 @@
+Wed Jul 09 04:44:24 UTC 2025 - Johannes Kastl 
<opensuse_buildserv...@ojkastl.de>
+
+- Update to version 0.29.1:
+  * Revert "feat: allow symlinks in workspaces (#2064)" (#2071)
+  * fix: avoid running cachedir mount commands via script (#2070)
+  * Add comment about PATH vs the qemu runner (#2069)
+  * SCA: Generate provides for shlibs ending with ".so" (#2067)
+  * licensing: default to concatenating with AND, add simple mode
+    for license-check --fix (#2057)
+
+-------------------------------------------------------------------

Old:
----
  melange-0.29.0.obscpio

New:
----
  melange-0.29.1.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ melange.spec ++++++
--- /var/tmp/diff_new_pack.iY3Gcv/_old  2025-07-09 17:29:33.326420939 +0200
+++ /var/tmp/diff_new_pack.iY3Gcv/_new  2025-07-09 17:29:33.330421106 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           melange
-Version:        0.29.0
+Version:        0.29.1
 Release:        0
 Summary:        Build APKs from source code
 License:        Apache-2.0

++++++ _service ++++++
--- /var/tmp/diff_new_pack.iY3Gcv/_old  2025-07-09 17:29:33.358422275 +0200
+++ /var/tmp/diff_new_pack.iY3Gcv/_new  2025-07-09 17:29:33.362422441 +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.29.0</param>
+    <param name="revision">v0.29.1</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="versionrewrite-pattern">v(.*)</param>
     <param name="changesgenerate">enable</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.iY3Gcv/_old  2025-07-09 17:29:33.382423276 +0200
+++ /var/tmp/diff_new_pack.iY3Gcv/_new  2025-07-09 17:29:33.386423443 +0200
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param 
name="url">https://github.com/chainguard-dev/melange</param>
-              <param 
name="changesrevision">75ee8c561e307394b4b565e6e7b23ce7cf059245</param></service></servicedata>
+              <param 
name="changesrevision">15d3e93dd6c3501bb04bf1b206c1cb6d97165347</param></service></servicedata>
 (No newline at EOF)
 

++++++ melange-0.29.0.obscpio -> melange-0.29.1.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.29.0/docs/md/melange_license-check.md 
new/melange-0.29.1/docs/md/melange_license-check.md
--- old/melange-0.29.0/docs/md/melange_license-check.md 2025-07-03 
19:44:54.000000000 +0200
+++ new/melange-0.29.1/docs/md/melange_license-check.md 2025-07-08 
17:06:52.000000000 +0200
@@ -29,6 +29,7 @@
 
 ```
       --fix              fix license issues in the melange yaml file
+      --format string    license fix strategy format: 'simple' or 'flat' 
(default "flat")
   -h, --help             help for license-check
       --workdir string   path to the working directory, e.g. where the source 
will be extracted to
 ```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/melange-0.29.0/e2e-tests/symlinks-in-workspace-build.yaml 
new/melange-0.29.1/e2e-tests/symlinks-in-workspace-build.yaml
--- old/melange-0.29.0/e2e-tests/symlinks-in-workspace-build.yaml       
2025-07-03 19:44:54.000000000 +0200
+++ new/melange-0.29.1/e2e-tests/symlinks-in-workspace-build.yaml       
1970-01-01 01:00:00.000000000 +0100
@@ -1,17 +0,0 @@
-package:
-  name: symlinks-in-workspace-build
-  description: Test that symlinks are copied into workspaces
-  version: 0.1.0
-  epoch: 0
-
-environment:
-  contents:
-    packages:
-      - busybox
-
-pipeline:
-  - name: Test for symlink presence in workspace
-    runs: |
-      testdata_linked=$(cat testdata-symlink.txt)
-      testdata=$(cat testdata.txt)
-      [ "$testdata" = "$testdata_linked" ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/melange-0.29.0/e2e-tests/test-fixtures/testdata-symlink.txt 
new/melange-0.29.1/e2e-tests/test-fixtures/testdata-symlink.txt
--- old/melange-0.29.0/e2e-tests/test-fixtures/testdata-symlink.txt     
2025-07-09 17:29:33.558430620 +0200
+++ new/melange-0.29.1/e2e-tests/test-fixtures/testdata-symlink.txt     
1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-symbolic link to testdata.txt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.29.0/e2e-tests/test-fixtures/testdata.txt 
new/melange-0.29.1/e2e-tests/test-fixtures/testdata.txt
--- old/melange-0.29.0/e2e-tests/test-fixtures/testdata.txt     2025-07-03 
19:44:54.000000000 +0200
+++ new/melange-0.29.1/e2e-tests/test-fixtures/testdata.txt     1970-01-01 
01:00:00.000000000 +0100
@@ -1 +0,0 @@
-test data is present
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.29.0/pkg/build/build.go 
new/melange-0.29.1/pkg/build/build.go
--- old/melange-0.29.0/pkg/build/build.go       2025-07-03 19:44:54.000000000 
+0200
+++ new/melange-0.29.1/pkg/build/build.go       2025-07-08 17:06:52.000000000 
+0200
@@ -563,25 +563,7 @@
 
                mode := fi.Mode()
                if !mode.IsRegular() {
-                       // If this file is a symlink to a regular file, include 
it.
-                       // It would be easier to include all symlinks but that 
breaks
-                       // when the top-level workspace directory is a symlink.
-                       if mode&fs.ModeSymlink != 0 {
-                               targetPath, err := 
filepath.EvalSymlinks(filepath.Join(b.SourceDir, path))
-                               if err != nil {
-                                       log.Debugf("path %s eval gives err %v", 
path, err)
-                                       return err
-                               }
-                               target, err := os.Stat(targetPath)
-                               if err != nil {
-                                       return err
-                               }
-                               if !target.Mode().IsRegular() {
-                                       return nil
-                               }
-                       } else {
-                               return nil
-                       }
+                       return nil
                }
 
                for _, pat := range ignorePatterns {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.29.0/pkg/build/pipeline.go 
new/melange-0.29.1/pkg/build/pipeline.go
--- old/melange-0.29.0/pkg/build/pipeline.go    2025-07-03 19:44:54.000000000 
+0200
+++ new/melange-0.29.1/pkg/build/pipeline.go    2025-07-08 17:06:52.000000000 
+0200
@@ -207,6 +207,7 @@
 
        // Pipelines can have their own environment variables, which override 
the global ones.
        envOverride := map[string]string{
+               // NOTE: This does not currently override PATH in the qemu 
runner, that's set at openssh build time
                "PATH": 
"/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin",
        }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.29.0/pkg/build/test.go 
new/melange-0.29.1/pkg/build/test.go
--- old/melange-0.29.0/pkg/build/test.go        2025-07-03 19:44:54.000000000 
+0200
+++ new/melange-0.29.1/pkg/build/test.go        2025-07-08 17:06:52.000000000 
+0200
@@ -334,6 +334,8 @@
                        }
 
                        log.Infof("running the main test pipeline")
+
+                       pr.config.TestRun = true
                        if err := pr.runPipelines(ctx, 
t.Configuration.Test.Pipeline); err != nil {
                                return fmt.Errorf("unable to run pipeline: %w", 
err)
                        }
@@ -388,6 +390,7 @@
                                }()
                        }
 
+                       pr.config.TestRun = true
                        if err := pr.runPipelines(ctx, sp.Test.Pipeline); err 
!= nil {
                                return fmt.Errorf("unable to run pipeline: %w", 
err)
                        }
@@ -452,7 +455,6 @@
                Environment:  map[string]string{},
                RunAsUID:     runAsUID(imgcfg.Accounts),
                RunAs:        runAs(imgcfg.Accounts),
-               TestRun:      true,
        }
        if t.Configuration.Capabilities.Add != nil {
                cfg.Capabilities.Add = t.Configuration.Capabilities.Add
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.29.0/pkg/build/test_test.go 
new/melange-0.29.1/pkg/build/test_test.go
--- old/melange-0.29.0/pkg/build/test_test.go   2025-07-03 19:44:54.000000000 
+0200
+++ new/melange-0.29.1/pkg/build/test_test.go   2025-07-08 17:06:52.000000000 
+0200
@@ -78,7 +78,6 @@
                PackageName:  testPkgName,
                ImgRef:       testImgRef,
                WorkspaceDir: "/workspace",
-               TestRun:      true,
                Capabilities: container.Capabilities{Networking: true},
                Mounts: []container.BindMount{
                        {Source: testWorkspaceDir, Destination: homeBuild},
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.29.0/pkg/cli/license_check.go 
new/melange-0.29.1/pkg/cli/license_check.go
--- old/melange-0.29.0/pkg/cli/license_check.go 2025-07-03 19:44:54.000000000 
+0200
+++ new/melange-0.29.1/pkg/cli/license_check.go 2025-07-08 17:06:52.000000000 
+0200
@@ -32,6 +32,7 @@
 func licenseCheck() *cobra.Command {
        var workDir string
        var fix bool
+       var format string
        cmd := &cobra.Command{
                Use:     "license-check file",
                Short:   "Gather and check licensing data",
@@ -81,6 +82,7 @@
                                        ctx,
                                        
copyright.WithLicenses(detectedLicenses),
                                        copyright.WithDiffs(diffs),
+                                       copyright.WithFormat(format),
                                )
                                err = rc.Renovate(cmd.Context(), 
copyrightRenovator)
                        }
@@ -91,6 +93,7 @@
 
        cmd.Flags().StringVar(&workDir, "workdir", "", "path to the working 
directory, e.g. where the source will be extracted to")
        cmd.Flags().BoolVar(&fix, "fix", false, "fix license issues in the 
melange yaml file")
+       cmd.Flags().StringVar(&format, "format", "flat", "license fix strategy 
format: 'simple' or 'flat'")
 
        return cmd
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.29.0/pkg/config/config.go 
new/melange-0.29.1/pkg/config/config.go
--- old/melange-0.29.0/pkg/config/config.go     2025-07-03 19:44:54.000000000 
+0200
+++ new/melange-0.29.1/pkg/config/config.go     2025-07-08 17:06:52.000000000 
+0200
@@ -432,7 +432,7 @@
        }
        for _, cp := range p.Copyright {
                if licenseExpression != "" {
-                       licenseExpression += " OR "
+                       licenseExpression += " AND "
                }
                licenseExpression += cp.License
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.29.0/pkg/renovate/copyright/copyright.go 
new/melange-0.29.1/pkg/renovate/copyright/copyright.go
--- old/melange-0.29.0/pkg/renovate/copyright/copyright.go      2025-07-03 
19:44:54.000000000 +0200
+++ new/melange-0.29.1/pkg/renovate/copyright/copyright.go      2025-07-08 
17:06:52.000000000 +0200
@@ -17,6 +17,9 @@
 import (
        "context"
        "fmt"
+       "maps"
+       "slices"
+       "strings"
 
        "github.com/chainguard-dev/clog"
 
@@ -30,6 +33,7 @@
 type CopyrightConfig struct {
        Licenses []license.License
        Diffs    []license.LicenseDiff
+       Format   string // "simple" or "flat"
 }
 
 // Option sets a config option on a CopyrightConfig.
@@ -53,6 +57,16 @@
        }
 }
 
+// WithFormat sets whether the copyright should be populated with a single
+// node containing all detected licenses joined together (simple), or with
+// multiple nodes, one per license (flat).
+func WithFormat(format string) Option {
+       return func(cfg *CopyrightConfig) error {
+               cfg.Format = format
+               return nil
+       }
+}
+
 // New returns a renovator which performs a copyright update.
 func New(ctx context.Context, opts ...Option) renovate.Renovator {
        log := clog.FromContext(ctx)
@@ -104,46 +118,98 @@
                copyrightNode.Content = nil
 
                // Repopulate the copyrightNode with detected licenses
-               for _, l := range ccfg.Licenses {
-                       // Skip licenses we don't have full confidence in.
-                       if !license.IsLicenseMatchConfident(l) {
-                               log.Infof("skipping unconfident license %s", 
l.Source)
-                               continue
+               if ccfg.Format == "simple" {
+                       // Make the copyright field a single node with all 
licenses joined together
+                       if err = populateSimpleCopyright(ctx, copyrightNode, 
ccfg.Licenses); err != nil {
+                               return err
                        }
-
-                       licenseNode := &yaml.Node{
-                               Kind:    yaml.MappingNode,
-                               Style:   yaml.FlowStyle,
-                               Content: []*yaml.Node{},
+               } else {
+                       // Use flat license listing (original behavior)
+                       if err = populateFlatCopyright(ctx, copyrightNode, 
ccfg.Licenses); err != nil {
+                               return err
                        }
+               }
 
-                       licenseNode.Content = append(licenseNode.Content, 
&yaml.Node{
-                               Kind:  yaml.ScalarNode,
-                               Value: "license",
-                               Tag:   "!!str",
-                               Style: yaml.FlowStyle,
-                       }, &yaml.Node{
-                               Kind:  yaml.ScalarNode,
-                               Value: l.Name,
-                               Tag:   "!!str",
-                               Style: yaml.FlowStyle,
-                       })
-
-                       licenseNode.Content = append(licenseNode.Content, 
&yaml.Node{
-                               Kind:  yaml.ScalarNode,
-                               Value: "license-path",
-                               Tag:   "!!str",
-                               Style: yaml.FlowStyle,
-                       }, &yaml.Node{
-                               Kind:  yaml.ScalarNode,
-                               Value: l.Source,
-                               Tag:   "!!str",
-                               Style: yaml.FlowStyle,
-                       })
+               return nil
+       }
+}
 
-                       copyrightNode.Content = append(copyrightNode.Content, 
licenseNode)
+// populateFlatCopyright populates the copyright node with the detected 
licenses,
+// one entry per license.
+func populateFlatCopyright(ctx context.Context, copyrightNode *yaml.Node, 
licenses []license.License) error {
+       log := clog.FromContext(ctx)
+
+       for _, l := range licenses {
+               // Skip licenses we don't have full confidence in.
+               if !license.IsLicenseMatchConfident(l) {
+                       log.Infof("skipping unconfident license %s", l.Source)
+                       continue
+               }
+
+               licenseNode := &yaml.Node{
+                       Kind:    yaml.MappingNode,
+                       Style:   yaml.FlowStyle,
+                       Content: []*yaml.Node{},
+               }
+
+               licenseNode.Content = append(licenseNode.Content, &yaml.Node{
+                       Kind:  yaml.ScalarNode,
+                       Value: "license",
+                       Tag:   "!!str",
+                       Style: yaml.FlowStyle,
+               }, &yaml.Node{
+                       Kind:  yaml.ScalarNode,
+                       Value: l.Name,
+                       Tag:   "!!str",
+                       Style: yaml.FlowStyle,
+               })
+
+               licenseNode.Content = append(licenseNode.Content, &yaml.Node{
+                       Kind:  yaml.ScalarNode,
+                       Value: "license-path",
+                       Tag:   "!!str",
+                       Style: yaml.FlowStyle,
+               }, &yaml.Node{
+                       Kind:  yaml.ScalarNode,
+                       Value: l.Source,
+                       Tag:   "!!str",
+                       Style: yaml.FlowStyle,
+               })
+
+               copyrightNode.Content = append(copyrightNode.Content, 
licenseNode)
+       }
+
+       return nil
+}
+
+// populateSimpleCopyright populates the copyright field with a single node
+// with all detected licenses joined together.
+func populateSimpleCopyright(ctx context.Context, copyrightNode *yaml.Node, 
licenses []license.License) error {
+       log := clog.FromContext(ctx)
+
+       // Gather all the license names and concatenate them with AND statements
+       licenseMap := make(map[string]struct{})
+       for _, l := range licenses {
+               if !license.IsLicenseMatchConfident(l) {
+                       log.Infof("skipping unconfident license %s", l.Source)
+                       continue
                }
+               licenseMap[l.Name] = struct{}{}
+       }
 
+       if len(licenseMap) == 0 {
+               log.Infof("no confident licenses found to populate copyright")
                return nil
        }
+
+       // Join the license names with " AND ", sorting them first for 
consistency
+       ls := slices.Collect(maps.Keys(licenseMap))
+       slices.Sort(ls)
+       combined := strings.Join(ls, " AND ")
+
+       copyrightNode.Kind = yaml.ScalarNode
+       copyrightNode.Value = combined
+       copyrightNode.Tag = "!!str"
+
+       return nil
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/melange-0.29.0/pkg/renovate/copyright/copyright_test.go 
new/melange-0.29.1/pkg/renovate/copyright/copyright_test.go
--- old/melange-0.29.0/pkg/renovate/copyright/copyright_test.go 2025-07-03 
19:44:54.000000000 +0200
+++ new/melange-0.29.1/pkg/renovate/copyright/copyright_test.go 2025-07-08 
17:06:52.000000000 +0200
@@ -126,3 +126,66 @@
        assert.Contains(t, string(resultData), "license: Not-Applicable")
        assert.NotContains(t, string(resultData), "license: Invalid")
 }
+
+func TestCopyright_updateSimple(t *testing.T) {
+       dir := t.TempDir()
+       ctx := slogtest.Context(t)
+
+       detectedLicenses := []license.License{
+               {
+                       Name:       "Apache-2.0",
+                       Source:     "LICENSE",
+                       Confidence: 1.0,
+               },
+               {
+                       Name:       "MIT",
+                       Source:     "internal/COPYING",
+                       Confidence: 1.0,
+               },
+               {
+                       Name:       "Apache-2.0",
+                       Source:     "vendor/foo/LICENSE",
+                       Confidence: 1.0,
+               },
+               {
+                       Name:       "GPL-3.0",
+                       Source:     "internal/LICENSE",
+                       Confidence: 0.2,
+               },
+       }
+
+       diffs := []license.LicenseDiff{
+               {
+                       Path:   "LICENSE",
+                       Is:     "GPL-2.0",
+                       Should: "Apache-2.0",
+               },
+       }
+
+       // Copy the test data file to the temp directory
+       src := filepath.Join("testdata", "nolicense.yaml")
+       testFile := filepath.Join(dir, "nolicense.yaml")
+       input, err := os.ReadFile(src)
+       assert.NoError(t, err)
+
+       err = os.WriteFile(testFile, input, 0644)
+       assert.NoError(t, err)
+
+       rctx, err := renovate.New(renovate.WithConfig(testFile))
+       assert.NoError(t, err)
+
+       copyrightRenovator := New(ctx, WithLicenses(detectedLicenses), 
WithDiffs(diffs), WithFormat("simple"))
+
+       err = rctx.Renovate(slogtest.Context(t), copyrightRenovator)
+       assert.NoError(t, err)
+
+       resultData, err := os.ReadFile(testFile)
+       assert.NoError(t, err)
+
+       // The copyright field should be a single string with both licenses 
joined by " AND "
+       result := string(resultData)
+       assert.Contains(t, result, "Apache-2.0 AND MIT")
+       assert.NotContains(t, result, "GPL-3.0")
+       assert.NotContains(t, result, "NOASSERTION")
+       assert.NotContains(t, result, "license:")
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/melange-0.29.0/pkg/sca/sca.go 
new/melange-0.29.1/pkg/sca/sca.go
--- old/melange-0.29.0/pkg/sca/sca.go   2025-07-03 19:44:54.000000000 +0200
+++ new/melange-0.29.1/pkg/sca/sca.go   2025-07-08 17:06:52.000000000 +0200
@@ -622,7 +622,7 @@
                //
                // As a rough heuristic, we assume that if the filename 
contains ".so.",
                // it is meant to be used as a shared object.
-               if interp == "" || strings.Contains(basename, ".so.") {
+               if interp == "" || strings.Contains(basename, ".so.") || 
strings.HasSuffix(basename, ".so") {
                        sonames, err := ef.DynString(elf.DT_SONAME)
                        // most likely SONAME is not set on this object
                        if err != nil {

++++++ melange.obsinfo ++++++
--- /var/tmp/diff_new_pack.iY3Gcv/_old  2025-07-09 17:29:33.650434459 +0200
+++ /var/tmp/diff_new_pack.iY3Gcv/_new  2025-07-09 17:29:33.654434626 +0200
@@ -1,5 +1,5 @@
 name: melange
-version: 0.29.0
-mtime: 1751564694
-commit: 75ee8c561e307394b4b565e6e7b23ce7cf059245
+version: 0.29.1
+mtime: 1751987212
+commit: 15d3e93dd6c3501bb04bf1b206c1cb6d97165347
 

++++++ vendor.tar.gz ++++++
/work/SRC/openSUSE:Factory/melange/vendor.tar.gz 
/work/SRC/openSUSE:Factory/.melange.new.7373/vendor.tar.gz differ: char 132, 
line 1

Reply via email to