fix: emit lua rockspec dependencies in metadata (#4376)

The types / schema allowed for this field to begin with but it wasn't
set.

Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>
This commit is contained in:
Will Murphy 2025-11-18 09:19:41 -05:00 committed by GitHub
parent 7014cb023f
commit 759909f611
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 147 additions and 2 deletions

View File

@ -35,6 +35,7 @@ func parseRockspec(ctx context.Context, resolver file.Resolver, _ *generic.Envir
} }
var name, version, license, homepage, description, url string var name, version, license, homepage, description, url string
var dependencies map[string]string
for _, node := range doc.value { for _, node := range doc.value {
switch node.key { switch node.key {
@ -60,6 +61,16 @@ func parseRockspec(ctx context.Context, resolver file.Resolver, _ *generic.Envir
license = strings.ReplaceAll(child.String(), " ", "-") license = strings.ReplaceAll(child.String(), " ", "-")
} }
} }
case "dependencies":
if dependencies == nil {
dependencies = make(map[string]string)
}
for _, child := range node.Slice() {
depName, depVersion := parseDependency(child.String())
if depName != "" {
dependencies[depName] = depVersion
}
}
} }
} }
@ -75,9 +86,32 @@ func parseRockspec(ctx context.Context, resolver file.Resolver, _ *generic.Envir
}, },
Homepage: homepage, Homepage: homepage,
Description: description, Description: description,
Dependencies: dependencies,
}, },
reader.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), reader.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
) )
return []pkg.Package{p}, nil, nil return []pkg.Package{p}, nil, nil
} }
// parseDependency extracts the package name and version constraint from a dependency string.
// Examples:
// - "lua >= 5.1" -> ("lua", ">= 5.1")
// - "lpeg" -> ("lpeg", "")
// - "lualogging >= 1.4.0, < 2.0.0" -> ("lualogging", ">= 1.4.0, < 2.0.0")
func parseDependency(dep string) (name string, version string) {
dep = strings.TrimSpace(dep)
if dep == "" {
return "", ""
}
// Find the first space which separates package name from version constraint
parts := strings.SplitN(dep, " ", 2)
name = strings.TrimSpace(parts[0])
if len(parts) == 2 {
version = strings.TrimSpace(parts[1])
}
return name, version
}

View File

@ -4,6 +4,8 @@ import (
"context" "context"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
@ -33,6 +35,38 @@ func TestParseRockspec(t *testing.T) {
Homepage: "https://konghq.com", Homepage: "https://konghq.com",
Description: "Kong is a scalable and customizable API Management Layer built on top of Nginx.", Description: "Kong is a scalable and customizable API Management Layer built on top of Nginx.",
URL: "git+https://github.com/Kong/kong.git", URL: "git+https://github.com/Kong/kong.git",
Dependencies: map[string]string{
"inspect": "== 3.1.3",
"luasec": "== 1.3.2",
"luasocket": "== 3.0-rc1",
"penlight": "== 1.13.1",
"lua-resty-http": "== 0.17.1",
"lua-resty-jit-uuid": "== 0.0.7",
"lua-ffi-zlib": "== 0.6",
"multipart": "== 0.5.9",
"version": "== 1.0.1",
"kong-lapis": "== 1.16.0.1",
"kong-pgmoon": "== 1.16.2",
"luatz": "== 0.4",
"lua_system_constants": "== 0.1.4",
"lyaml": "== 6.2.8",
"luasyslog": "== 2.0.1",
"lua_pack": "== 2.0.0",
"binaryheap": ">= 0.4",
"luaxxhash": ">= 1.0",
"lua-protobuf": "== 0.5.0",
"lua-resty-healthcheck": "== 3.0.1",
"lua-messagepack": "== 0.5.4",
"lua-resty-aws": "== 1.3.6",
"lua-resty-openssl": "== 1.2.0",
"lua-resty-counter": "== 0.2.1",
"lua-resty-ipmatcher": "== 0.6.1",
"lua-resty-acme": "== 0.12.0",
"lua-resty-session": "== 4.0.5",
"lua-resty-timer-ng": "== 0.2.6",
"lpeg": "== 1.1.0",
"lua-resty-ljsonschema": "== 1.1.6-2",
},
}, },
}, },
}, },
@ -54,6 +88,9 @@ func TestParseRockspec(t *testing.T) {
Homepage: "http://www.inf.puc-rio.br/~roberto/lpeg.html", Homepage: "http://www.inf.puc-rio.br/~roberto/lpeg.html",
Description: "Parsing Expression Grammars For Lua", Description: "Parsing Expression Grammars For Lua",
URL: "http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.2.tar.gz", URL: "http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.2.tar.gz",
Dependencies: map[string]string{
"lua": ">= 5.1",
},
}, },
}, },
}, },
@ -75,6 +112,10 @@ func TestParseRockspec(t *testing.T) {
Homepage: "https://github.com/Kong/pgmoon", Homepage: "https://github.com/Kong/pgmoon",
Description: "Postgres driver for OpenResty and Lua", Description: "Postgres driver for OpenResty and Lua",
URL: "git+https://github.com/kong/pgmoon.git", URL: "git+https://github.com/kong/pgmoon.git",
Dependencies: map[string]string{
"lua": ">= 5.1",
"lpeg": "",
},
}, },
}, },
}, },
@ -96,6 +137,10 @@ func TestParseRockspec(t *testing.T) {
Homepage: "https://github.com/lunarmodules/luasyslog", Homepage: "https://github.com/lunarmodules/luasyslog",
Description: "Syslog logging for Lua", Description: "Syslog logging for Lua",
URL: "git://github.com/lunarmodules/luasyslog.git", URL: "git://github.com/lunarmodules/luasyslog.git",
Dependencies: map[string]string{
"lua": ">= 5.1",
"lualogging": ">= 1.4.0, < 2.0.0",
},
}, },
}, },
}, },
@ -115,3 +160,69 @@ func Test_corruptRockspec(t *testing.T) {
WithError(). WithError().
TestParser(t, parseRockspec) TestParser(t, parseRockspec)
} }
func Test_parseDependency(t *testing.T) {
tests := []struct {
name string
input string
expectedName string
expectedVersion string
}{
{
name: "dependency with >= constraint",
input: "lua >= 5.1",
expectedName: "lua",
expectedVersion: ">= 5.1",
},
{
name: "dependency with == constraint",
input: "inspect == 3.1.3",
expectedName: "inspect",
expectedVersion: "== 3.1.3",
},
{
name: "dependency without constraint",
input: "lpeg",
expectedName: "lpeg",
expectedVersion: "",
},
{
name: "dependency with complex constraint",
input: "lualogging >= 1.4.0, < 2.0.0",
expectedName: "lualogging",
expectedVersion: ">= 1.4.0, < 2.0.0",
},
{
name: "dependency with version including dash",
input: "luasocket == 3.0-rc1",
expectedName: "luasocket",
expectedVersion: "== 3.0-rc1",
},
{
name: "dependency with extra whitespace",
input: " kong-pgmoon == 1.16.2 ",
expectedName: "kong-pgmoon",
expectedVersion: "== 1.16.2",
},
{
name: "empty string",
input: "",
expectedName: "",
expectedVersion: "",
},
{
name: "whitespace only",
input: " ",
expectedName: "",
expectedVersion: "",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actualName, actualVersion := parseDependency(test.input)
assert.Equal(t, test.expectedName, actualName)
assert.Equal(t, test.expectedVersion, actualVersion)
})
}
}