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-02-24 15:48:59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/melange (Old) and /work/SRC/openSUSE:Factory/.melange.new.1873 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "melange" Mon Feb 24 15:48:59 2025 rev:66 rq:1247995 version:0.21.1 Changes: -------- --- /work/SRC/openSUSE:Factory/melange/melange.changes 2025-02-20 22:05:12.763988325 +0100 +++ /work/SRC/openSUSE:Factory/.melange.new.1873/melange.changes 2025-02-24 15:49:19.440651707 +0100 @@ -1,0 +2,7 @@ +Mon Feb 24 06:03:12 UTC 2025 - opensuse_buildserv...@ojkastl.de + +- Update to version 0.21.1: + * Give better names for invalid pipelines errors (#1805) + * Fix pkgconf lint (#1802) + +------------------------------------------------------------------- Old: ---- melange-0.21.0.obscpio New: ---- melange-0.21.1.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ melange.spec ++++++ --- /var/tmp/diff_new_pack.TnWTXB/_old 2025-02-24 15:49:22.664786475 +0100 +++ /var/tmp/diff_new_pack.TnWTXB/_new 2025-02-24 15:49:22.680787144 +0100 @@ -17,7 +17,7 @@ Name: melange -Version: 0.21.0 +Version: 0.21.1 Release: 0 Summary: Build APKs from source code License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.TnWTXB/_old 2025-02-24 15:49:22.936797845 +0100 +++ /var/tmp/diff_new_pack.TnWTXB/_new 2025-02-24 15:49:22.972799350 +0100 @@ -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.21.0</param> + <param name="revision">v0.21.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.TnWTXB/_old 2025-02-24 15:49:23.156807042 +0100 +++ /var/tmp/diff_new_pack.TnWTXB/_new 2025-02-24 15:49:23.204809048 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/chainguard-dev/melange</param> - <param name="changesrevision">5695ed93d5ec3fa6219e2b8cff8c218286992155</param></service></servicedata> + <param name="changesrevision">61a593656a36cec46e0a8e96d0bd29bc4b409b36</param></service></servicedata> (No newline at EOF) ++++++ melange-0.21.0.obscpio -> melange-0.21.1.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.21.0/pkg/build/build.go new/melange-0.21.1/pkg/build/build.go --- old/melange-0.21.0/pkg/build/build.go 2025-02-19 19:39:51.000000000 +0100 +++ new/melange-0.21.1/pkg/build/build.go 2025-02-21 21:32:50.000000000 +0100 @@ -967,7 +967,7 @@ return a == b }) - if err := linter.LintBuild(ctx, lt.pkgName, path, require, warn); err != nil { + if err := linter.LintBuild(ctx, &b.Configuration, lt.pkgName, path, require, warn); err != nil { return fmt.Errorf("unable to lint package %s: %w", lt.pkgName, err) } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.21.0/pkg/config/config.go new/melange-0.21.1/pkg/config/config.go --- old/melange-0.21.0/pkg/config/config.go 2025-02-19 19:39:51.000000000 +0100 +++ new/melange-0.21.1/pkg/config/config.go 2025-02-21 21:32:50.000000000 +0100 @@ -1563,9 +1563,21 @@ return nil } +func pipelineName(p Pipeline, i int) string { + if p.Name != "" { + return strconv.Quote(p.Name) + } + + if p.Uses != "" { + return strconv.Quote(p.Uses) + } + + return fmt.Sprintf("[%d]", i) +} + func validatePipelines(ctx context.Context, ps []Pipeline) error { log := clog.FromContext(ctx) - for _, p := range ps { + for i, p := range ps { if p.With != nil && p.Uses == "" { return fmt.Errorf("pipeline contains with but no uses") } @@ -1575,7 +1587,7 @@ } if p.Uses != "" && len(p.Pipeline) > 0 { - log.Warnf("pipeline %q contains both uses and a pipeline", p.Name) + log.Warnf("pipeline %s contains both uses and a pipeline", pipelineName(p, i)) } if len(p.With) > 0 && p.Runs != "" { @@ -1583,7 +1595,7 @@ } if err := validatePipelines(ctx, p.Pipeline); err != nil { - return err + return fmt.Errorf("validating pipeline %s children: %w", pipelineName(p, i), err) } } return nil diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.21.0/pkg/linter/linter.go new/melange-0.21.1/pkg/linter/linter.go --- old/melange-0.21.0/pkg/linter/linter.go 2025-02-19 19:39:51.000000000 +0100 +++ new/melange-0.21.1/pkg/linter/linter.go 2025-02-21 21:32:50.000000000 +0100 @@ -36,9 +36,10 @@ "chainguard.dev/apko/pkg/apk/auth" "chainguard.dev/apko/pkg/apk/expandapk" + "chainguard.dev/melange/pkg/config" ) -type linterFunc func(ctx context.Context, pkgname string, fsys fs.FS) error +type linterFunc func(ctx context.Context, cfg *config.Configuration, pkgname string, fsys fs.FS) error type linter struct { LinterFunc linterFunc @@ -57,8 +58,8 @@ Warn ) -func allPaths(fn func(ctx context.Context, pkgname, path string) error) func(ctx context.Context, pkgname string, fsys fs.FS) error { - return func(ctx context.Context, pkgname string, fsys fs.FS) error { +func allPaths(fn func(ctx context.Context, cfg *config.Configuration, pkgname, path string) error) func(ctx context.Context, cfg *config.Configuration, pkgname string, fsys fs.FS) error { + return func(ctx context.Context, cfg *config.Configuration, pkgname string, fsys fs.FS) error { return fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error { if err := ctx.Err(); err != nil { return err @@ -70,7 +71,7 @@ // Ignore directories return nil } - if err := fn(ctx, pkgname, path); err != nil { + if err := fn(ctx, cfg, pkgname, path); err != nil { return fmt.Errorf("%w: %s", err, path) } return nil @@ -193,21 +194,21 @@ return strings.HasPrefix(path, "var/lib/db/sbom/") } -func devLinter(_ context.Context, _, path string) error { +func devLinter(_ context.Context, _ *config.Configuration, _, path string) error { if strings.HasPrefix(path, "dev/") { return fmt.Errorf("package writes to /dev") } return nil } -func optLinter(_ context.Context, _, path string) error { +func optLinter(_ context.Context, _ *config.Configuration, _, path string) error { if strings.HasPrefix(path, "opt/") { return fmt.Errorf("package writes to /opt") } return nil } -func objectLinter(_ context.Context, _, path string) error { +func objectLinter(_ context.Context, _ *config.Configuration, _, path string) error { if filepath.Ext(path) == ".o" { return fmt.Errorf("package contains intermediate object file %q. This is usually wrong. In most cases they should be removed", path) } @@ -216,14 +217,14 @@ var isDocumentationFileRegex = regexp.MustCompile(`(?:READ(?:\.?ME)?|TODO|CREDITS|\.(?:md|docx?|rst|[0-9][a-z]))$`) -func documentationLinter(_ context.Context, pkgname, path string) error { +func documentationLinter(_ context.Context, _ *config.Configuration, pkgname, path string) error { if isDocumentationFileRegex.MatchString(path) && !strings.HasSuffix(pkgname, "-doc") { return errors.New("package contains documentation files but is not a documentation package") } return nil } -func isSetUIDOrGIDLinter(ctx context.Context, _ string, fsys fs.FS) error { +func isSetUIDOrGIDLinter(ctx context.Context, _ *config.Configuration, _ string, fsys fs.FS) error { return fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error { if err := ctx.Err(); err != nil { return err @@ -250,21 +251,21 @@ }) } -func sbomLinter(_ context.Context, _, path string) error { +func sbomLinter(_ context.Context, _ *config.Configuration, _, path string) error { if strings.HasPrefix(path, "var/lib/db/sbom/") { return fmt.Errorf("package writes to %s", path) } return nil } -func infodirLinter(_ context.Context, _, path string) error { +func infodirLinter(_ context.Context, _ *config.Configuration, _, path string) error { if strings.HasPrefix(path, "usr/share/info/dir/") { return fmt.Errorf("package writes to /usr/share/info/dir/") } return nil } -func srvLinter(_ context.Context, _, path string) error { +func srvLinter(_ context.Context, _ *config.Configuration, _, path string) error { if strings.HasPrefix(path, "srv/") { return fmt.Errorf("package writes to /srv") } @@ -273,28 +274,28 @@ var isTempDirRegex = regexp.MustCompile("^(var/)?(tmp|run)/") -func tempDirLinter(_ context.Context, _, path string) error { +func tempDirLinter(_ context.Context, _ *config.Configuration, _, path string) error { if isTempDirRegex.MatchString(path) { return fmt.Errorf("package writes to a temp dir") } return nil } -func usrLocalLinter(_ context.Context, _, path string) error { +func usrLocalLinter(_ context.Context, _ *config.Configuration, _, path string) error { if strings.HasPrefix(path, "usr/local/") { return fmt.Errorf("/usr/local path found in non-compat package") } return nil } -func varEmptyLinter(_ context.Context, _, path string) error { +func varEmptyLinter(_ context.Context, _ *config.Configuration, _, path string) error { if strings.HasPrefix(path, "var/empty/") { return fmt.Errorf("package writes to /var/empty") } return nil } -func worldWriteableLinter(ctx context.Context, pkgname string, fsys fs.FS) error { +func worldWriteableLinter(ctx context.Context, _ *config.Configuration, pkgname string, fsys fs.FS) error { return fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error { if err := ctx.Err(); err != nil { return err @@ -330,7 +331,7 @@ var isObjectFileRegex = regexp.MustCompile(`\.(a|so|dylib)(\..*)?`) -func strippedLinter(ctx context.Context, _ string, fsys fs.FS) error { +func strippedLinter(ctx context.Context, _ *config.Configuration, _ string, fsys fs.FS) error { return fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error { if err := ctx.Err(); err != nil { return err @@ -401,7 +402,7 @@ }) } -func emptyLinter(ctx context.Context, pkgname string, fsys fs.FS) error { +func emptyLinter(ctx context.Context, _ *config.Configuration, pkgname string, fsys fs.FS) error { foundfile := false err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error { if err := ctx.Err(); err != nil { @@ -461,7 +462,7 @@ return } -func pythonDocsLinter(_ context.Context, _ string, fsys fs.FS) error { +func pythonDocsLinter(_ context.Context, _ *config.Configuration, _ string, fsys fs.FS) error { packages, err := getPythonSitePackages(fsys) if err != nil { return err @@ -477,7 +478,7 @@ return nil } -func pythonMultiplePackagesLinter(_ context.Context, _ string, fsys fs.FS) error { +func pythonMultiplePackagesLinter(_ context.Context, _ *config.Configuration, _ string, fsys fs.FS) error { packages, err := getPythonSitePackages(fsys) if err != nil { return err @@ -533,7 +534,7 @@ return nil } -func pythonTestLinter(_ context.Context, _ string, fsys fs.FS) error { +func pythonTestLinter(_ context.Context, _ *config.Configuration, _ string, fsys fs.FS) error { packages, err := getPythonSitePackages(fsys) if err != nil { return err @@ -551,14 +552,47 @@ var PkgconfDirRegex = regexp.MustCompile("^usr/(lib|share)/pkgconfig/") -func pkgconfTestLinter(_ context.Context, _, path string) error { - if PkgconfDirRegex.MatchString(path) { - return fmt.Errorf("pkgconfig directory found") +func pkgconfTestLinter(_ context.Context, cfg *config.Configuration, pkgname, path string) error { + if !PkgconfDirRegex.MatchString(path) { + return nil } - return nil + + if cfg == nil { + return fmt.Errorf("pkgconfig directory found and missing .melange.yaml") + } + + if cfg.Package.Name == pkgname { + if cfg.Test != nil { + for _, test := range cfg.Test.Pipeline { + if test.Uses == "test/pkgconf" { + return nil + } + } + } + } else { + for _, p := range cfg.Subpackages { + if p.Name != pkgname { + continue + } + + if p.Test == nil { + break + } + + for _, test := range p.Test.Pipeline { + if test.Uses == "test/pkgconf" { + return nil + } + } + + break + } + } + + return fmt.Errorf("pkgconfig directory found") } -func lintPackageFS(ctx context.Context, pkgname string, fsys fs.FS, linters []string) error { +func lintPackageFS(ctx context.Context, cfg *config.Configuration, pkgname string, fsys fs.FS, linters []string) error { // If this is a compat package, do nothing. if strings.HasSuffix(pkgname, "-compat") { return nil @@ -570,7 +604,7 @@ return err } linter := linterMap[linterName] - if err := linter.LinterFunc(ctx, linterName, fsys); err != nil { + if err := linter.LinterFunc(ctx, cfg, pkgname, fsys); err != nil { errs = append(errs, fmt.Errorf("linter %q failed on package %q: %w; suggest: %s", linterName, pkgname, err, linter.Explain)) } } @@ -589,7 +623,7 @@ } // Lint the given build directory at the given path -func LintBuild(ctx context.Context, packageName string, path string, require, warn []string) error { +func LintBuild(ctx context.Context, cfg *config.Configuration, packageName string, path string, require, warn []string) error { if err := checkLinters(append(require, warn...)); err != nil { return err } @@ -597,11 +631,11 @@ log := clog.FromContext(ctx) fsys := os.DirFS(path) - if err := lintPackageFS(ctx, packageName, fsys, warn); err != nil { + if err := lintPackageFS(ctx, cfg, packageName, fsys, warn); err != nil { log.Warn(err.Error()) } log.Infof("linting apk: %s", packageName) - return lintPackageFS(ctx, packageName, fsys, require) + return lintPackageFS(ctx, cfg, packageName, fsys, require) } // Lint the given APK at the given path @@ -656,24 +690,58 @@ return fmt.Errorf("could not read from package: %w", err) } - cfg, err := ini.Load(data) + pkginfo, err := ini.Load(data) if err != nil { return fmt.Errorf("could not load .PKGINFO file: %w", err) } - pkgname := cfg.Section("").Key("pkgname").MustString("") + pkgname := pkginfo.Section("").Key("pkgname").MustString("") if pkgname == "" { return fmt.Errorf("pkgname is nonexistent") } + cfg, err := parseMelangeYaml(ctx, exp.ControlFS) + if err != nil { + // TODO: Consider making this fatal if the universe gets rebuilt with new melange. + clog.FromContext(ctx).Warnf("parsing .melange.yaml: %v", err) + } + log.Infof("linting apk: %s (size: %s)", pkgname, humanize.Bytes(uint64(exp.Size))) - if err := lintPackageFS(ctx, pkgname, exp.TarFS, warn); err != nil { + if err := lintPackageFS(ctx, cfg, pkgname, exp.TarFS, warn); err != nil { log.Warn(err.Error()) } - return lintPackageFS(ctx, pkgname, exp.TarFS, require) + return lintPackageFS(ctx, cfg, pkgname, exp.TarFS, require) +} + +func parseMelangeYaml(ctx context.Context, fsys fs.FS) (*config.Configuration, error) { + my, err := fsys.Open(".melange.yaml") + if err != nil { + return nil, fmt.Errorf("could not open .melange.yaml file: %w", err) + } + defer my.Close() + + tmp, err := os.CreateTemp("", ".melange.yaml") + if err != nil { + return nil, fmt.Errorf("creating temp file: %w", err) + } + defer os.Remove(tmp.Name()) + + if _, err := io.Copy(tmp, my); err != nil { + return nil, fmt.Errorf("copying .melange.yaml: %w", err) + } + if err := tmp.Close(); err != nil { + return nil, fmt.Errorf("closing temp file: %w", err) + } + + cfg, err := config.ParseConfiguration(ctx, tmp.Name()) + if err != nil { + return nil, fmt.Errorf("parsing .melange.yaml: %w", err) + } + + return cfg, nil } -func usrmergeLinter(_ context.Context, _, path string) error { +func usrmergeLinter(_ context.Context, _ *config.Configuration, _, path string) error { if strings.HasPrefix(path, "sbin") { return fmt.Errorf("package writes to /sbin in violation of usrmerge") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/melange-0.21.0/pkg/linter/linter_test.go new/melange-0.21.1/pkg/linter/linter_test.go --- old/melange-0.21.0/pkg/linter/linter_test.go 2025-02-19 19:39:51.000000000 +0100 +++ new/melange-0.21.1/pkg/linter/linter_test.go 2025-02-21 21:32:50.000000000 +0100 @@ -21,6 +21,7 @@ "path/filepath" "testing" + "chainguard.dev/melange/pkg/config" "github.com/chainguard-dev/clog/slogtest" "github.com/stretchr/testify/assert" ) @@ -38,9 +39,44 @@ } } + cfg := &config.Configuration{ + Package: config.Package{ + Name: "pkgconf", + }, + } + + goodCfg := &config.Configuration{ + Package: config.Package{ + Name: "pkgconf", + }, + Test: &config.Test{ + Pipeline: []config.Pipeline{{ + Uses: "test/pkgconf", + }}, + }, + } + + subpkgCfg := &config.Configuration{ + Package: config.Package{ + Name: "not-pkgconf", + }, + Subpackages: []config.Subpackage{{ + Name: "also-not-pkgconf", + }, { + Name: "pkgconf", + Test: &config.Test{ + Pipeline: []config.Pipeline{{ + Uses: "test/pkgconf", + }}, + }, + }}, + } + for _, c := range []struct { + cfg *config.Configuration dirFunc func() string - linter string + linter string // NB: Also the package name for this test, but that's weird! + pass bool }{{ dirFunc: t.TempDir, linter: "empty", @@ -83,9 +119,21 @@ }, { dirFunc: mkfile(t, "usr/lib/pkgconfig/test.txt"), linter: "pkgconf", + cfg: cfg, + }, { + dirFunc: mkfile(t, "usr/lib/pkgconfig/test.txt"), + linter: "pkgconf", + cfg: goodCfg, + pass: true, + }, { + dirFunc: mkfile(t, "usr/lib/pkgconfig/test.txt"), + linter: "pkgconf", + cfg: subpkgCfg, + pass: true, }, { dirFunc: mkfile(t, "usr/share/pkgconfig/test.txt"), linter: "pkgconf", + cfg: cfg, }, { dirFunc: mkfile(t, "sbin/test.sh"), linter: "usrmerge", @@ -94,10 +142,15 @@ t.Run(c.linter, func(t *testing.T) { dir := c.dirFunc() // In required mode, it should raise an error. - assert.Error(t, LintBuild(ctx, c.linter, dir, []string{c.linter}, nil)) + err := LintBuild(ctx, c.cfg, c.linter, dir, []string{c.linter}, nil) + if c.pass { + assert.NoError(t, err) + } else { + assert.Error(t, err) + } // In warn mode, it should never raise an error. - assert.NoError(t, LintBuild(ctx, c.linter, dir, nil, []string{c.linter})) + assert.NoError(t, LintBuild(ctx, c.cfg, c.linter, dir, nil, []string{c.linter})) }) } } @@ -116,32 +169,32 @@ assert.NoError(t, os.MkdirAll(packagedir, 0700)) // One package should not trip it - assert.NoError(t, LintBuild(ctx, "multiple", dir, linters, nil)) + assert.NoError(t, LintBuild(ctx, nil, "multiple", dir, linters, nil)) // Egg info files should not count _, err := os.Create(filepath.Join(pythonPathdir, "fooegg-0.1-py3.14.egg-info")) assert.NoError(t, err) - assert.NoError(t, LintBuild(ctx, "multiple", dir, linters, nil)) + assert.NoError(t, LintBuild(ctx, nil, "multiple", dir, linters, nil)) // dist info files should not count _, err = os.Create(filepath.Join(pythonPathdir, "foodist-0.1-py3.14.dist-info")) assert.NoError(t, err) - assert.NoError(t, LintBuild(ctx, "multiple", dir, linters, nil)) + assert.NoError(t, LintBuild(ctx, nil, "multiple", dir, linters, nil)) // pth files should not count _, err = os.Create(filepath.Join(pythonPathdir, "foopth-0.1-py3.14.pth")) assert.NoError(t, err) - assert.NoError(t, LintBuild(ctx, "multiple", dir, linters, nil)) + assert.NoError(t, LintBuild(ctx, nil, "multiple", dir, linters, nil)) // .so files duplicate with a dir should not count _, err = os.Create(filepath.Join(pythonPathdir, "foo.so")) assert.NoError(t, err) - assert.NoError(t, LintBuild(ctx, "multiple", dir, linters, nil)) + assert.NoError(t, LintBuild(ctx, nil, "multiple", dir, linters, nil)) // __pycache__ dirs should not count err = os.MkdirAll(filepath.Join(pythonPathdir, "__pycache__"), 0700) assert.NoError(t, err) - assert.NoError(t, LintBuild(ctx, "multiple", dir, linters, nil)) + assert.NoError(t, LintBuild(ctx, nil, "multiple", dir, linters, nil)) // Make another "package" (at this point we should have 2) packagedir = filepath.Join(pythonPathdir, "bar") @@ -149,7 +202,7 @@ assert.NoError(t, err) // Two should trip it - assert.Error(t, LintBuild(ctx, "multiple", dir, linters, nil)) + assert.Error(t, LintBuild(ctx, nil, "multiple", dir, linters, nil)) } func Test_pythonTestLinter(t *testing.T) { @@ -167,14 +220,14 @@ assert.NoError(t, os.MkdirAll(packagedir, 0700)) // One package should not trip it - assert.NoError(t, LintBuild(ctx, "python-test", dir, linters, nil)) + assert.NoError(t, LintBuild(ctx, nil, "python-test", dir, linters, nil)) // Create docs docsdir := filepath.Join(pythonPathdir, "test") assert.NoError(t, os.MkdirAll(docsdir, 0700)) // This should trip - assert.Error(t, LintBuild(ctx, "python-test", dir, linters, nil)) + assert.Error(t, LintBuild(ctx, nil, "python-test", dir, linters, nil)) } func Test_setUidGidLinter(t *testing.T) { @@ -187,7 +240,7 @@ assert.NoError(t, err) assert.NoError(t, f.Close()) assert.NoError(t, os.Chmod(filePath, 0770|fs.ModeSetuid|fs.ModeSetgid)) - assert.NoError(t, LintBuild(ctx, "setuidgid", t.TempDir(), linters, nil)) + assert.NoError(t, LintBuild(ctx, nil, "setuidgid", t.TempDir(), linters, nil)) } func Test_worldWriteLinter(t *testing.T) { @@ -199,7 +252,7 @@ assert.NoError(t, os.MkdirAll(filepath.Join(dir, "usr", "lib"), 0777)) // Ensure 777 dirs don't trigger it - assert.NoError(t, LintBuild(ctx, "worldwrite", dir, linters, nil)) + assert.NoError(t, LintBuild(ctx, nil, "worldwrite", dir, linters, nil)) // Create test file filePath := filepath.Join(dir, "usr", "lib", "test.txt") @@ -211,21 +264,21 @@ assert.NoError(t, err) // Linter should not trigger - assert.NoError(t, LintBuild(ctx, "worldwrite", dir, linters, nil)) + assert.NoError(t, LintBuild(ctx, nil, "worldwrite", dir, linters, nil)) // Set writeable bit (but not executable bit) err = os.Chmod(filePath, 0776) assert.NoError(t, err) // Linter should trigger - assert.Error(t, LintBuild(ctx, "worldwrite", dir, linters, nil)) + assert.Error(t, LintBuild(ctx, nil, "worldwrite", dir, linters, nil)) // Set writeable and executable bit err = os.Chmod(filePath, 0777) assert.NoError(t, err) // Linter should trigger - assert.Error(t, LintBuild(ctx, "worldwrite", dir, linters, nil)) + assert.Error(t, LintBuild(ctx, nil, "worldwrite", dir, linters, nil)) } func Test_lintApk(t *testing.T) { ++++++ melange.obsinfo ++++++ --- /var/tmp/diff_new_pack.TnWTXB/_old 2025-02-24 15:49:24.304855030 +0100 +++ /var/tmp/diff_new_pack.TnWTXB/_new 2025-02-24 15:49:24.328856033 +0100 @@ -1,5 +1,5 @@ name: melange -version: 0.21.0 -mtime: 1739990391 -commit: 5695ed93d5ec3fa6219e2b8cff8c218286992155 +version: 0.21.1 +mtime: 1740169970 +commit: 61a593656a36cec46e0a8e96d0bd29bc4b409b36 ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/melange/vendor.tar.gz /work/SRC/openSUSE:Factory/.melange.new.1873/vendor.tar.gz differ: char 5, line 1