Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
<modelVersion>4.0.0</modelVersion>
<groupId>foo</groupId>
<artifactId>bar</artifactId>
<version>1.2.3</version>
<version>1.2.3.rhlw-00001</version>
</project>
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
<modelVersion>4.0.0</modelVersion>
<groupId>foo</groupId>
<artifactId>bar</artifactId>
<version>2.0.1</version>
<version>1.2.3.rhlw-00002</version>
</project>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>foo</groupId>
<artifactId>bar</artifactId>
<version>2.0.1.rhlw-00001</version>
</project>
Binary file not shown.
46 changes: 25 additions & 21 deletions internal/test/integration/maven_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,18 @@ const (
testMavenContentOrigin = "http://localhost:8088"
testMavenGroupID = "foo"
testMavenArtifactID = "bar"
testMavenVersion123 = "1.2.3"
testMavenVersion201 = "2.0.1"
testMavenBuildVersion123R1 = "1.2.3.rhlw-00001"
testMavenBuildVersion123R2 = "1.2.3.rhlw-00002"
testMavenBuildVersion201R1 = "2.0.1.rhlw-00001"
)

var testMavenArtifactPaths = []string{
"foo/bar/1.2.3/foo.bar.1.2.3.pom",
"foo/bar/1.2.3/foo.bar.1.2.3.rhlw-00001.jar",
"foo/bar/1.2.3/foo.bar.1.2.3.rhlw-00002.jar",
"foo/bar/2.0.1/foo.bar.2.0.1.pom",
"foo/bar/2.0.1/foo.bar.2.0.1.rhlw-00001.jar",
"foo/bar/1.2.3.rhlw-00001/foo.bar.1.2.3.rhlw-00001.pom",
"foo/bar/1.2.3.rhlw-00001/foo.bar.1.2.3.rhlw-00001.jar",
"foo/bar/1.2.3.rhlw-00002/foo.bar.1.2.3.rhlw-00002.pom",
"foo/bar/1.2.3.rhlw-00002/foo.bar.1.2.3.rhlw-00002.jar",
"foo/bar/2.0.1.rhlw-00001/foo.bar.2.0.1.rhlw-00001.pom",
"foo/bar/2.0.1.rhlw-00001/foo.bar.2.0.1.rhlw-00001.jar",
}

type MavenSuite struct {
Expand Down Expand Up @@ -105,17 +107,19 @@ func (m *MavenSuite) TestMavenPackageList() {
pkg := response.Results[0]
assert.Equal(m.T(), testMavenGroupID, pkg.GroupID)
assert.Equal(m.T(), testMavenArtifactID, pkg.ArtifactID)
assert.Contains(m.T(), pkg.Versions, testMavenVersion123)
assert.Contains(m.T(), pkg.Versions, testMavenVersion201)
assert.Contains(m.T(), pkg.Versions, testMavenBuildVersion123R1)
assert.Contains(m.T(), pkg.Versions, testMavenBuildVersion123R2)
assert.Contains(m.T(), pkg.Versions, testMavenBuildVersion201R1)
require.NotEmpty(m.T(), pkg.LatestReleases)

foundVersions := make(map[string]bool)
for _, latest := range pkg.LatestReleases {
foundVersions[latest.Version] = true
assert.NotEmpty(m.T(), latest.CreatedAt)
}
assert.True(m.T(), foundVersions[testMavenVersion123])
assert.True(m.T(), foundVersions[testMavenVersion201])
assert.True(m.T(), foundVersions[testMavenBuildVersion123R1])
assert.True(m.T(), foundVersions[testMavenBuildVersion123R2])
assert.True(m.T(), foundVersions[testMavenBuildVersion201R1])
}

func (m *MavenSuite) TestMavenPackageListSearchFilter() {
Expand Down Expand Up @@ -169,7 +173,7 @@ func (m *MavenSuite) TestMavenBuildList() {
m.repositoryHref,
testMavenGroupID,
testMavenArtifactID,
testMavenVersion123,
testMavenBuildVersion123R1,
tangy.PageOptions{Offset: 0, Limit: 10},
)
require.NoError(m.T(), err)
Expand All @@ -180,7 +184,7 @@ func (m *MavenSuite) TestMavenBuildList() {
build := response.Results[0]
assert.Equal(m.T(), testMavenGroupID, build.GroupID)
assert.Equal(m.T(), testMavenArtifactID, build.ArtifactID)
assert.Equal(m.T(), testMavenVersion123, build.Version)
assert.Equal(m.T(), testMavenBuildVersion123R1, build.Version)
assert.True(m.T(), strings.HasSuffix(build.Filename, ".pom"), build.Filename)
assert.NotEmpty(m.T(), build.CreatedAt)
}
Expand All @@ -191,7 +195,7 @@ func (m *MavenSuite) TestMavenBuildListPagination() {
m.repositoryHref,
testMavenGroupID,
testMavenArtifactID,
testMavenVersion123,
testMavenBuildVersion123R1,
tangy.PageOptions{Offset: 0, Limit: 1},
)
require.NoError(m.T(), err)
Expand All @@ -203,7 +207,7 @@ func (m *MavenSuite) TestMavenBuildListPagination() {
m.repositoryHref,
testMavenGroupID,
testMavenArtifactID,
testMavenVersion123,
testMavenBuildVersion123R1,
tangy.PageOptions{Offset: 1, Limit: 10},
)
require.NoError(m.T(), err)
Expand All @@ -212,7 +216,7 @@ func (m *MavenSuite) TestMavenBuildListPagination() {
}

func (m *MavenSuite) TestMavenBuildListEmptyHref() {
response, err := m.tangy.MavenBuildList(context.Background(), "", testMavenGroupID, testMavenArtifactID, testMavenVersion123, tangy.PageOptions{Limit: 10})
response, err := m.tangy.MavenBuildList(context.Background(), "", testMavenGroupID, testMavenArtifactID, testMavenBuildVersion123R1, tangy.PageOptions{Limit: 10})
require.NoError(m.T(), err)
assert.Empty(m.T(), response.Results)
assert.Zero(m.T(), response.Total)
Expand All @@ -229,7 +233,7 @@ func (m *MavenSuite) TestMavenBuildListOptionalFilters() {
)
require.NoError(m.T(), err)
require.NotEmpty(m.T(), response.Results)
assert.Equal(m.T(), 2, response.Total)
assert.Equal(m.T(), 3, response.Total)

build := response.Results[0]
assert.Equal(m.T(), testMavenGroupID, build.GroupID)
Expand All @@ -244,8 +248,8 @@ func (m *MavenSuite) TestMavenBuildListOptionalFilters() {
tangy.PageOptions{Offset: 0, Limit: 10},
)
require.NoError(m.T(), err)
require.Len(m.T(), filtered.Results, 2)
assert.Equal(m.T(), 2, filtered.Total)
require.Len(m.T(), filtered.Results, 3)
assert.Equal(m.T(), 3, filtered.Total)

filtered, err = m.tangy.MavenBuildList(
context.Background(),
Expand All @@ -256,8 +260,8 @@ func (m *MavenSuite) TestMavenBuildListOptionalFilters() {
tangy.PageOptions{Offset: 0, Limit: 10},
)
require.NoError(m.T(), err)
require.Len(m.T(), filtered.Results, 2)
assert.Equal(m.T(), 2, filtered.Total)
require.Len(m.T(), filtered.Results, 3)
assert.Equal(m.T(), 3, filtered.Total)
}

func (m *MavenSuite) TestMavenRepositoryMetrics() {
Expand Down
38 changes: 26 additions & 12 deletions pkg/tangy/maven.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,13 +243,26 @@ func (t *tangyImpl) MavenPackageList(ctx context.Context, repositoryHref string,
}, nil
}

const mavenReleaseQualifierPattern = `[a-zA-Z]+-\d+`

const mavenReleaseVersionSuffixPattern = `\.` + mavenReleaseQualifierPattern + `$`

const mavenReleaseFilenamePattern = `\.(` + mavenReleaseQualifierPattern + `)\.pom$`

var mavenReleaseVersionSuffixRegexp = regexp.MustCompile(mavenReleaseVersionSuffixPattern)

var mavenReleaseFilenameRegexp = regexp.MustCompile(mavenReleaseFilenamePattern)

// stripMavenReleaseVersion removes a trailing release qualifier from a Maven version string.
// Example: 5.3.18.rhlw-00003 -> 5.3.18
func stripMavenReleaseVersion(version string) string {
return mavenReleaseVersionSuffixRegexp.ReplaceAllString(version, "")
}

// extractRelease extracts the release version from a filename
// Example: smallrye-mutiny-vertx-core-3.16.0.rhlw-3002.pom -> rhlw-3002
func extractRelease(filename string) string {
// Pattern to match .rhlw-XXXX or similar release patterns before .pom
// Looks for a dot followed by alphanumeric+dash, then .pom
re := regexp.MustCompile(`\.([a-zA-Z]+-\d+)\.pom$`)
matches := re.FindStringSubmatch(filename)
matches := mavenReleaseFilenameRegexp.FindStringSubmatch(filename)
if len(matches) > 1 {
return matches[1]
}
Expand Down Expand Up @@ -411,7 +424,8 @@ func (t *tangyImpl) MavenBuildList(ctx context.Context, repositoryHref, groupID,
}

// MavenRepositoryMetrics returns package, build, and version counts for the latest version of a repository.
// Packages are distinct group_id/artifact_id pairs from .pom artifacts; builds and versions are counted from .jar artifacts.
// All counts are based on .jar artifacts. Builds are distinct full versions (e.g. 5.3.18.rhlw-00003);
// versions are distinct base versions with release qualifiers stripped (e.g. 5.3.18).
func (t *tangyImpl) MavenRepositoryMetrics(ctx context.Context, repositoryHref string) (MavenRepositoryMetrics, error) {
if repositoryHref == "" {
return MavenRepositoryMetrics{}, nil
Expand Down Expand Up @@ -444,22 +458,22 @@ func (t *tangyImpl) MavenRepositoryMetrics(ctx context.Context, repositoryHref s
return MavenRepositoryMetrics{}, err
}

pomFilter := ` AND rp.filename LIKE '%.pom'`
jarFilter := ` AND rp.filename LIKE '%.jar'`
pomFrom := `
FROM maven_mavenartifact rp
` + innerUnion + pomFilter
jarFrom := `
FROM maven_mavenartifact rp
` + innerUnion + jarFilter

metricsQuery := `
SELECT
(SELECT COUNT(DISTINCT (rp.group_id, rp.artifact_id))
` + pomFrom + `) AS package_count,
(SELECT COUNT(*)
` + jarFrom + `) AS build_count,
` + jarFrom + `) AS package_count,
(SELECT COUNT(DISTINCT (rp.group_id, rp.artifact_id, rp.version))
` + jarFrom + `) AS build_count,
(SELECT COUNT(DISTINCT (
rp.group_id,
rp.artifact_id,
regexp_replace(rp.version, '` + mavenReleaseVersionSuffixPattern + `', '')
))
` + jarFrom + `) AS version_count`

var metrics MavenRepositoryMetrics
Expand Down
109 changes: 109 additions & 0 deletions pkg/tangy/maven_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,115 @@ func TestParseRepositoryHref(t *testing.T) {
}
}

func TestStripMavenReleaseVersion(t *testing.T) {
t.Parallel()

tests := []struct {
name string
version string
want string
}{
{
name: "release suffix in version",
version: "5.3.18.rhlw-00003",
want: "5.3.18",
},
{
name: "plain version",
version: "1.2.3",
want: "1.2.3",
},
{
name: "final qualifier version",
version: "4.1.114.Final",
want: "4.1.114.Final",
},
{
name: "empty version",
version: "",
want: "",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
assert.Equal(t, tt.want, stripMavenReleaseVersion(tt.version))
})
}
}

func TestMavenRepositoryMetricsCounting(t *testing.T) {
t.Parallel()

type artifact struct {
group string
artifact string
version string
}

countMetrics := func(artifacts []artifact) (packageCount, buildCount, versionCount int) {
packages := make(map[[2]string]struct{})
builds := make(map[[3]string]struct{})
versions := make(map[[3]string]struct{})

for _, a := range artifacts {
packages[[2]string{a.group, a.artifact}] = struct{}{}
builds[[3]string{a.group, a.artifact, a.version}] = struct{}{}
baseVersion := stripMavenReleaseVersion(a.version)
versions[[3]string{a.group, a.artifact, baseVersion}] = struct{}{}
}

return len(packages), len(builds), len(versions)
}

springCoreVersions := []string{
"5.3.18.rhlw-00003",
"5.3.18.rhlw-00004",
"5.3.18.rhlw-00005",
"5.3.18.rhlw-00006",
"5.3.18.rhlw-00007",
}
springCoreArtifacts := make([]artifact, 0, len(springCoreVersions)*3)
for _, version := range springCoreVersions {
for range 3 {
springCoreArtifacts = append(springCoreArtifacts, artifact{
group: "org.springframework",
artifact: "spring-core",
version: version,
})
}
}

nettyVersions := []string{
"4.1.114.Final",
"4.1.127.Final",
"4.1.128.Final",
"4.1.130.Final",
"4.1.133.Final",
}
nettyArtifacts := make([]artifact, 0, len(nettyVersions)*5)
for _, version := range nettyVersions {
for range 5 {
nettyArtifacts = append(nettyArtifacts, artifact{
group: "io.netty",
artifact: "netty-codec",
version: version,
})
}
}

packageCount, buildCount, versionCount := countMetrics(springCoreArtifacts)
assert.Equal(t, 1, packageCount)
assert.Equal(t, 5, buildCount)
assert.Equal(t, 1, versionCount)

packageCount, buildCount, versionCount = countMetrics(nettyArtifacts)
assert.Equal(t, 1, packageCount)
assert.Equal(t, 5, buildCount)
assert.Equal(t, 5, versionCount)
}

func TestExtractRelease(t *testing.T) {
t.Parallel()

Expand Down
Loading