Skip to content

Commit

Permalink
linter: update usrmerge and make it required (#1839)
Browse files Browse the repository at this point in the history
Co-authored-by: Justin Vreeland <[email protected]>
  • Loading branch information
justinvreeland and Justin Vreeland authored Mar 11, 2025
1 parent 7600d7b commit 09ae0e6
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 18 deletions.
4 changes: 2 additions & 2 deletions docs/md/melange_build.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ melange build [flags]
-i, --interactive when enabled, attaches stdin with a tty to the pod on failure
-k, --keyring-append strings path to extra keys to include in the build environment keyring
--license string license to use for the build config file itself (default "NOASSERTION")
--lint-require strings linters that must pass (default [dev,infodir,tempdir,varempty])
--lint-warn strings linters that will generate warnings (default [lddcheck,object,opt,pkgconf,python/docs,python/multiple,python/test,setuidgid,srv,strip,usrlocal,usrmerge,worldwrite])
--lint-require strings linters that must pass (default [dev,infodir,tempdir,usrmerge,varempty])
--lint-warn strings linters that will generate warnings (default [lddcheck,object,opt,pkgconf,python/docs,python/multiple,python/test,setuidgid,srv,strip,usrlocal,worldwrite])
--memory string default memory resources to use for builds
--namespace string namespace to use in package URLs in SBOM (eg wolfi, alpine) (default "unknown")
--out-dir string directory where packages will be output (default "./packages/")
Expand Down
4 changes: 2 additions & 2 deletions docs/md/melange_lint.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ melange lint [flags]

```
-h, --help help for lint
--lint-require strings linters that must pass (default [dev,infodir,tempdir,varempty])
--lint-warn strings linters that will generate warnings (default [lddcheck,object,opt,pkgconf,python/docs,python/multiple,python/test,setuidgid,srv,strip,usrlocal,usrmerge,worldwrite])
--lint-require strings linters that must pass (default [dev,infodir,tempdir,usrmerge,varempty])
--lint-warn strings linters that will generate warnings (default [lddcheck,object,opt,pkgconf,python/docs,python/multiple,python/test,setuidgid,srv,strip,usrlocal,worldwrite])
```

### Options inherited from parent commands
Expand Down
46 changes: 32 additions & 14 deletions pkg/linter/linter.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,9 @@ var linterMap = map[string]linter{
defaultBehavior: Warn,
},
"usrmerge": {
LinterFunc: allPaths(usrmergeLinter),
Explain: "Move binary to /usr/{bin,lib/sbin}",
defaultBehavior: Warn,
LinterFunc: usrmergeLinter,
Explain: "Move binary to /usr/{bin,sbin}",
defaultBehavior: Require,
},
}

Expand Down Expand Up @@ -777,18 +777,36 @@ func parseMelangeYaml(fsys fs.FS) (*config.Configuration, error) {
return &cfg, nil
}

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")
}
func usrmergeLinter(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
}
if err != nil {
return err
}
if isIgnoredPath(path) {
return nil
}

if strings.HasPrefix(path, "lib") {
return fmt.Errorf("package writes to /lib in violation of usrmerge")
}
// We don't really care if a package is re-adding a symlink and this catches wolfi-baselayout
// without special casing it with the package name.
if path == "sbin" || path == "bin" {
if d.IsDir() || d.Type().IsRegular() {
return fmt.Errorf("package contains non-symlink file at /sbin or /bin in violation of usrmerge")
} else {
return nil
}
}

if strings.HasPrefix(path, "bin") {
return fmt.Errorf("package writes to /bin in violation of usrmerge")
}
if strings.HasPrefix(path, "sbin") {
return fmt.Errorf("package writes to /sbin in violation of usrmerge: %s", path)
}

return nil
if strings.HasPrefix(path, "bin") {
return fmt.Errorf("package writes to /bin in violation of usrmerge: %s", path)
}

return nil
})
}
27 changes: 27 additions & 0 deletions pkg/linter/linter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,33 @@ func TestLinters(t *testing.T) {
}, {
dirFunc: mkfile(t, "sbin/test.sh"),
linter: "usrmerge",
pass: false,
}, {
dirFunc: mkfile(t, "sbin"),
linter: "usrmerge",
pass: false,
}, {
dirFunc: mkfile(t, "bin"),
linter: "usrmerge",
pass: false,
}, {
dirFunc: func() string {
d := t.TempDir()
assert.NoError(t, os.MkdirAll(filepath.Join(d, filepath.Dir("/sbin")), 0700))
_ = os.Symlink("/sbin", "/dev/null")
return d
},
linter: "usrmerge",
pass: true,
}, {
dirFunc: func() string {
d := t.TempDir()
assert.NoError(t, os.MkdirAll(filepath.Join(d, filepath.Dir("/bin")), 0700))
_ = os.Symlink("/bin", "/dev/null")
return d
},
linter: "usrmerge",
pass: true,
}} {
ctx := slogtest.Context(t)
t.Run(c.linter, func(t *testing.T) {
Expand Down

0 comments on commit 09ae0e6

Please sign in to comment.