Skip to content

Commit 938fcf9

Browse files
Added support for new grouped dependencies (#54)
Co-authored-by: Bob Evans <robert.evans25@gmail.com>
1 parent 21f1e40 commit 938fcf9

4 files changed

Lines changed: 143 additions & 23 deletions

File tree

parse-package.go

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"fmt"
66
"regexp"
7+
"slices"
78
"strings"
89

910
"blitznote.com/src/semver/v3"
@@ -84,35 +85,68 @@ func findMinimumSupported(target Target, tests []TestDescription) (*semver.Range
8485
continue
8586
}
8687

87-
// We need to find the minimum version of the target module by looking
88-
// through the dependencies list and the inspecting the semver range
89-
// strings associated with it.
90-
for key, val := range test.Dependencies {
91-
if key != target.Name {
88+
if test.Dependencies != nil {
89+
// We need to find the minimum version of the target module by looking
90+
// through the dependencies list and the inspecting the semver range
91+
// strings associated with it.
92+
for key, val := range test.Dependencies {
93+
if key != target.Name {
94+
continue
95+
}
96+
97+
var currentVersion semver.Range
98+
99+
// The semver library does not parse strings like `>1.0.0 <2.0.0 || >3.0.0`.
100+
// So we need to split it up and normalize the pieces into range strings
101+
// it can understand.
102+
rangeStrings := strings.Split(val.Versions, "||")
103+
for k, v := range rangeStrings {
104+
// Oh, Go, why no slices.Map?
105+
rangeStrings[k] = normalizeRangeString(v)
106+
}
107+
108+
currentVersion, err := processRangeStrings(rangeStrings)
109+
if err != nil {
110+
return nil, fmt.Errorf("`%s` => `%s`: %w", target, val.Versions, err)
111+
}
112+
113+
if lastVersion == nil {
114+
lastVersion = &currentVersion
115+
continue
116+
}
117+
118+
if isRangeLower(currentVersion, *lastVersion) == true {
119+
lastVersion = &currentVersion
120+
}
121+
}
122+
} else if test.GroupedDependencies != nil {
123+
// As above, but for a `groupedDependencies` block instead. We should
124+
// always have one or the other.
125+
if slices.Contains(test.GroupedDependencies.Packages, target.Name) == false {
126+
// We are trying to find the minimum version across all defined "test"
127+
// blocks for the given `target`. So we cannot return an error here
128+
// if the `target` is not found in the grouped packages list.
92129
continue
93130
}
94131

95132
var currentVersion semver.Range
96-
97-
// The semver library does not parse strings like `>1.0.0 <2.0.0 || >3.0.0`.
98-
// So we need to split it up and normalize the pieces into range strings
99-
// it can understand.
100-
rangeStrings := strings.Split(val.Versions, "||")
133+
rangeStrings := strings.Split(test.GroupedDependencies.Version, "||")
101134
for k, v := range rangeStrings {
102-
// Oh, Go, why no slices.Map?
103135
rangeStrings[k] = normalizeRangeString(v)
104136
}
105-
106137
currentVersion, err := processRangeStrings(rangeStrings)
107138
if err != nil {
108-
return nil, fmt.Errorf("`%s` => `%s`: %w", target, val.Versions, err)
139+
return nil, fmt.Errorf(
140+
"`%s` => `%s`: %w",
141+
target,
142+
test.GroupedDependencies.Version,
143+
err,
144+
)
109145
}
110-
111146
if lastVersion == nil {
112147
lastVersion = &currentVersion
113148
continue
114149
}
115-
116150
if isRangeLower(currentVersion, *lastVersion) == true {
117151
lastVersion = &currentVersion
118152
}

parse-package_test.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
package main
22

33
import (
4-
"blitznote.com/src/semver/v3"
54
"encoding/json"
6-
"github.com/stretchr/testify/assert"
7-
"github.com/stretchr/testify/require"
85
"os"
96
"testing"
7+
8+
"blitznote.com/src/semver/v3"
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
1011
)
1112

1213
func testPkg(t *testing.T, jsonFile string, expected []PkgInfo) {
@@ -123,6 +124,21 @@ func Test_ParsePackage(t *testing.T) {
123124
MinAgentVersion: "1.0.0",
124125
}})
125126
})
127+
128+
t.Run("handles both dependencies and groupedDependencies", func(t *testing.T) {
129+
testPkg(t, "testdata/grouped-dependencies.json", []PkgInfo{
130+
{
131+
Name: "foo",
132+
MinVersion: "4.0.0",
133+
MinAgentVersion: "1.0.0",
134+
},
135+
{
136+
Name: "baz",
137+
MinVersion: "5.0.0",
138+
MinAgentVersion: "1.0.0",
139+
},
140+
})
141+
})
126142
}
127143

128144
func Test_processRangeStrings(t *testing.T) {

testdata/grouped-dependencies.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "baseline-test",
3+
"comment": "Verifies that our tool can find targets in both `dependencies` and `groupedDependencies`.",
4+
"engines": {
5+
"node": ">=18.0.0"
6+
},
7+
"targets": [
8+
{"name": "foo", "minAgentVersion": "1.0.0"},
9+
{"name": "baz", "minAgentVersion": "1.0.0"}
10+
],
11+
"tests": [
12+
{
13+
"dependencies": {
14+
"foo": {
15+
"versions": ">=4.0.0",
16+
"samples": "2"
17+
}
18+
},
19+
"files": ["test1.js"]
20+
},
21+
{
22+
"groupedDependencies": {
23+
"version": ">=5.0.0",
24+
"packages": ["bar", "baz"]
25+
},
26+
"files": ["test2.js"]
27+
}
28+
]
29+
}

types.go

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"encoding/json"
66
"fmt"
7+
78
"github.com/spf13/cast"
89
)
910

@@ -72,11 +73,12 @@ type VersionedTestPackageJson struct {
7273
}
7374

7475
type TestDescription struct {
75-
Supported bool `json:"supported"`
76-
Comment string `json:"comment"`
77-
Engines EnginesBlock `json:"engines"`
78-
Dependencies DependenciesBlock `json:"dependencies"`
79-
Files FilesBlock `json:"files"`
76+
Supported bool `json:"supported"`
77+
Comment string `json:"comment"`
78+
Engines EnginesBlock `json:"engines"`
79+
Dependencies DependenciesBlock `json:"dependencies"`
80+
GroupedDependencies *GroupedDependencyBlock `json:"groupedDependencies"`
81+
Files FilesBlock `json:"files"`
8082
}
8183

8284
func (td *TestDescription) UnmarshalJSON(data []byte) error {
@@ -124,6 +126,13 @@ func (td *TestDescription) UnmarshalJSON(data []byte) error {
124126
return err
125127
}
126128
td.Dependencies = deps
129+
case "groupedDependencies":
130+
var deps GroupedDependencyBlock
131+
err := json.Unmarshal(*val, &deps)
132+
if err != nil {
133+
return err
134+
}
135+
td.GroupedDependencies = &deps
127136
case "files":
128137
var files FilesBlock
129138
err := json.Unmarshal(*val, &files)
@@ -150,6 +159,11 @@ type DependencyBlock struct {
150159
Samples int `json:"samples"`
151160
}
152161

162+
type GroupedDependencyBlock struct {
163+
Version string `json:"version"`
164+
Packages []string `json:"packages"`
165+
}
166+
153167
func (db *DependenciesBlock) UnmarshalJSON(data []byte) error {
154168
if bytes.Compare(data, []byte("null")) == 0 {
155169
return nil
@@ -210,3 +224,30 @@ func (db *DependencyBlock) UnmarshalJSON(data []byte) error {
210224

211225
return nil
212226
}
227+
228+
func (gd *GroupedDependencyBlock) UnmarshalJSON(data []byte) error {
229+
if bytes.Compare(data, []byte("null")) == 0 {
230+
return nil
231+
}
232+
233+
var decoded map[string]*json.RawMessage
234+
_ = json.Unmarshal(data, &decoded)
235+
236+
version := decoded["version"]
237+
if version == nil {
238+
return fmt.Errorf("missing version property: %s", data)
239+
}
240+
strVersion := string(*version)
241+
gd.Version = strVersion[1 : len(strVersion)-1]
242+
243+
var packages []string
244+
err := json.Unmarshal(*decoded["packages"], &packages)
245+
if err != nil {
246+
return fmt.Errorf("failed to decode packages property: %w", err)
247+
} else if packages == nil {
248+
return fmt.Errorf("missing packages property: %w", err)
249+
}
250+
gd.Packages = packages
251+
252+
return nil
253+
}

0 commit comments

Comments
 (0)