Skip to content

Commit 1a3e3bb

Browse files
authored
feat: Use dependency constraints specified in configuration (#1987)
The existing configuration found in .sidekick.toml has configuration like this: ```toml # Default package dependency versions. 'package:google_cloud_gax' = '^0.1.0' 'package:http' = '^1.3.0' ``` This PR honors those constraints when generating `pubspec.yaml`
1 parent fafba70 commit 1a3e3bb

File tree

2 files changed

+91
-38
lines changed

2 files changed

+91
-38
lines changed

internal/sidekick/internal/dart/annotate.go

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -182,16 +182,19 @@ type annotateModel struct {
182182
packagePrefixes map[string]string
183183
// A mapping from field IDs to fields for the fields we know to be required.
184184
requiredFields map[string]*api.Field
185+
// A mapping from a package name (e.g. "http") to its version constraint (e.g. "^1.3.0").
186+
dependencyConstraints map[string]string
185187
}
186188

187189
func newAnnotateModel(model *api.API) *annotateModel {
188190
return &annotateModel{
189-
model: model,
190-
state: model.State,
191-
imports: map[string]string{},
192-
packageMapping: map[string]string{},
193-
packagePrefixes: map[string]string{},
194-
requiredFields: map[string]*api.Field{},
191+
model: model,
192+
state: model.State,
193+
imports: map[string]string{},
194+
packageMapping: map[string]string{},
195+
packagePrefixes: map[string]string{},
196+
requiredFields: map[string]*api.Field{},
197+
dependencyConstraints: map[string]string{},
195198
}
196199
}
197200

@@ -247,6 +250,14 @@ func (annotate *annotateModel) annotateModel(options map[string]string) error {
247250
}
248251
protoPackage := keys[1]
249252
annotate.packagePrefixes[protoPackage] = definition
253+
case strings.HasPrefix(key, "package:"):
254+
// Version constraints for a package.
255+
//
256+
// Expressed as: 'package:<package name>' = '<version constraint>'
257+
// For example: 'package:http' = '^1.3.0'
258+
//
259+
// If the package is needed as a dependency, then this constract is used.
260+
annotate.dependencyConstraints[strings.TrimPrefix(key, "package:")] = definition
250261
}
251262
}
252263

@@ -281,7 +292,7 @@ func (annotate *annotateModel) annotateModel(options map[string]string) error {
281292
// Add the import for the google_cloud_gax package.
282293
annotate.imports["cloud_gax"] = commonImport
283294

284-
packageDependencies := calculateDependencies(annotate.imports)
295+
packageDependencies := calculateDependencies(annotate.imports, annotate.dependencyConstraints)
285296

286297
ann := &modelAnnotations{
287298
Parent: model,
@@ -336,18 +347,23 @@ func calculateRequiredFields(model *api.API) map[string]*api.Field {
336347
}
337348

338349
// calculateDependencies calculates package dependencies based on `package:` imports.
339-
func calculateDependencies(imports map[string]string) []packageDependency {
340-
var deps []packageDependency
350+
func calculateDependencies(imports map[string]string, constraints map[string]string) []packageDependency {
351+
deps := []packageDependency{}
341352

342353
for _, imp := range imports {
343-
if strings.HasPrefix(imp, "package:") {
344-
name := strings.TrimPrefix(imp, "package:")
354+
if name, hadPrefix := strings.CutPrefix(imp, "package:"); hadPrefix {
345355
name = strings.Split(name, "/")[0]
346356

347357
if !slices.ContainsFunc(deps, func(dep packageDependency) bool {
348358
return dep.Name == name
349359
}) {
350-
deps = append(deps, packageDependency{Name: name, Constraint: "any"})
360+
constraint := constraints[name]
361+
if len(constraint) == 0 {
362+
// TODO(https://github.com/googleapis/librarian/issues/1989):
363+
// Never emit "any" constraints.
364+
constraint = "any"
365+
}
366+
deps = append(deps, packageDependency{Name: name, Constraint: constraint})
351367
}
352368
}
353369
}

internal/sidekick/internal/dart/annotate_test.go

Lines changed: 63 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,64 @@ func TestAnnotateModel(t *testing.T) {
4343

4444
func TestAnnotateModel_Options(t *testing.T) {
4545
model := api.NewTestAPI([]*api.Message{}, []*api.Enum{}, []*api.Service{})
46-
annotate := newAnnotateModel(model)
47-
err := annotate.annotateModel(map[string]string{
48-
"version": "1.0.0",
49-
"part-file": "src/test.p.dart",
50-
})
51-
if err != nil {
52-
t.Fatal(err)
53-
}
5446

55-
codec := model.Codec.(*modelAnnotations)
56-
57-
if diff := cmp.Diff("1.0.0", codec.PackageVersion); diff != "" {
58-
t.Errorf("mismatch in Codec.PackageVersion (-want, +got)\n:%s", diff)
47+
var foo = []struct {
48+
options map[string]string
49+
verify func(*testing.T, *annotateModel)
50+
}{
51+
{
52+
map[string]string{"package-name-override": "google-cloud-type"},
53+
func(t *testing.T, am *annotateModel) {
54+
codec := model.Codec.(*modelAnnotations)
55+
if diff := cmp.Diff("google-cloud-type", codec.PackageName); diff != "" {
56+
t.Errorf("mismatch in Codec.PackageName (-want, +got)\n:%s", diff)
57+
}
58+
},
59+
},
60+
{
61+
map[string]string{"dev-dependencies": "test,mockito"},
62+
func(t *testing.T, am *annotateModel) {
63+
codec := model.Codec.(*modelAnnotations)
64+
if diff := cmp.Diff([]string{"test", "mockito", "lints"}, codec.DevDependencies); diff != "" {
65+
t.Errorf("mismatch in Codec.PackageName (-want, +got)\n:%s", diff)
66+
}
67+
},
68+
},
69+
{
70+
map[string]string{"version": "1.2.3"},
71+
func(t *testing.T, am *annotateModel) {
72+
codec := model.Codec.(*modelAnnotations)
73+
if diff := cmp.Diff("1.2.3", codec.PackageVersion); diff != "" {
74+
t.Errorf("mismatch in Codec.PackageVersion (-want, +got)\n:%s", diff)
75+
}
76+
},
77+
},
78+
{
79+
map[string]string{"part-file": "src/test.p.dart"},
80+
func(t *testing.T, am *annotateModel) {
81+
codec := model.Codec.(*modelAnnotations)
82+
if diff := cmp.Diff("src/test.p.dart", codec.PartFileReference); diff != "" {
83+
t.Errorf("mismatch in Codec.PartFileReference (-want, +got)\n:%s", diff)
84+
}
85+
},
86+
},
87+
{
88+
map[string]string{"package:http": "1.2.0"},
89+
func(t *testing.T, am *annotateModel) {
90+
if diff := cmp.Diff(map[string]string{"http": "1.2.0"}, am.dependencyConstraints); diff != "" {
91+
t.Errorf("mismatch in annotateModel.dependencyConstraints (-want, +got)\n:%s", diff)
92+
}
93+
},
94+
},
5995
}
60-
if diff := cmp.Diff("src/test.p.dart", codec.PartFileReference); diff != "" {
61-
t.Errorf("mismatch in Codec.PartFileReference (-want, +got)\n:%s", diff)
96+
97+
for _, tt := range foo {
98+
annotate := newAnnotateModel(model)
99+
err := annotate.annotateModel(tt.options)
100+
if err != nil {
101+
t.Fatal(err)
102+
}
103+
tt.verify(t, annotate)
62104
}
63105
}
64106

@@ -111,28 +153,23 @@ func TestCalculateDependencies(t *testing.T) {
111153
for _, test := range []struct {
112154
name string
113155
imports []string
114-
want []string
156+
want []packageDependency
115157
}{
116-
{name: "empty", imports: []string{}, want: []string{}},
117-
{name: "dart import", imports: []string{typedDataImport}, want: []string{}},
118-
{name: "package import", imports: []string{httpImport}, want: []string{"http"}},
119-
{name: "dart and package imports", imports: []string{typedDataImport, httpImport}, want: []string{"http"}},
158+
{name: "empty", imports: []string{}, want: []packageDependency{}},
159+
{name: "dart import", imports: []string{typedDataImport}, want: []packageDependency{}},
160+
{name: "package import", imports: []string{httpImport}, want: []packageDependency{{Name: "http", Constraint: "^1.3.0"}}},
161+
{name: "dart and package imports", imports: []string{typedDataImport, httpImport}, want: []packageDependency{{Name: "http", Constraint: "^1.3.0"}}},
120162
{name: "package imports", imports: []string{
121163
httpImport,
122164
"package:google_cloud_foo/foo.dart",
123-
}, want: []string{"google_cloud_foo", "http"}},
165+
}, want: []packageDependency{{Name: "google_cloud_foo", Constraint: "any"}, {Name: "http", Constraint: "^1.3.0"}}},
124166
} {
125167
t.Run(test.name, func(t *testing.T) {
126168
deps := map[string]string{}
127169
for _, imp := range test.imports {
128170
deps[imp] = imp
129171
}
130-
gotFull := calculateDependencies(deps)
131-
132-
got := []string{}
133-
for _, dep := range gotFull {
134-
got = append(got, dep.Name)
135-
}
172+
got := calculateDependencies(deps, map[string]string{"http": "^1.3.0"})
136173

137174
if diff := cmp.Diff(test.want, got); diff != "" {
138175
t.Errorf("mismatch in calculateDependencies (-want, +got)\n:%s", diff)

0 commit comments

Comments
 (0)