Skip to content

Commit 78269b3

Browse files
authored
Add warning (and flag) for unused YarnLink (#160)
Part of pulumi/home#4417 While working on pulumi/pulumi-gcp#3460, I discovered that the version of `@pulumi/pulumi-gcp` used on the NodeJS tests was not the module under test: We were effectively testing against old versions of the library instead of using the NodeJS provider SDK release candidates. I am adding a new `opttest.Option` boolean flag `RequireYarnLinks` that will gate the behavior of when `YarnLinks` have not been set. `RequireYarnLinks` has three possible values: * `nil` (or unset): Logs a warning if a NodeJS pulumi project does not specify at least one `YarnLink`. * `true`: Fail the test if there's not at least one `YarnLink`. * `false`: Suppress warning and silently ignore that there are no `YarnLink`s set. I am not sure if this would be immediately useful, but there may be some potential use case I don't know yet. Moving forward, on the next `pulumitest` major version bump, we should make the `RequireYarnLinks` flag default to `true`: That would mean that test authors would need to explicitly opt-out from requiring at least one `YarnLink`.
1 parent 5f5b841 commit 78269b3

File tree

7 files changed

+69
-2
lines changed

7 files changed

+69
-2
lines changed

pulumitest/grpcLog_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,23 @@ import (
66
"github.com/gkampitakis/go-snaps/match"
77
"github.com/gkampitakis/go-snaps/snaps"
88
"github.com/pulumi/providertest/pulumitest"
9+
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
910
"github.com/stretchr/testify/assert"
1011
)
1112

1213
func TestGrpc(t *testing.T) {
1314
t.Parallel()
1415
test := pulumitest.NewPulumiTest(t, "testdata/yaml_program")
16+
17+
versionCmd := test.CurrentStack().Workspace().PulumiCommand()
18+
version, _, _, err := versionCmd.Run(test.Context(), test.WorkingDir(), nil, nil, nil, nil, "version")
19+
contract.AssertNoErrorf(err, "failed to get pulumi version: %s", version)
20+
t.Logf("pulumi version: %s", version)
21+
22+
plugins, _, _, err := versionCmd.Run(test.Context(), test.WorkingDir(), nil, nil, nil, nil, "plugin", "ls", "-p")
23+
contract.AssertNoErrorf(err, "failed to get pulumi plugins: %s", plugins)
24+
t.Logf("pulumi plugins: %s", plugins)
25+
1526
test.Up(t)
1627
log := test.GrpcLog(t)
1728
assert.NotEmpty(t, log)

pulumitest/newStack.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ func (pt *PulumiTest) NewStack(t PT, stackName string, opts ...optnewstack.NewSt
136136
}
137137
}
138138

139-
if options.YarnLinks != nil && len(options.YarnLinks) > 0 {
139+
if len(options.YarnLinks) > 0 {
140140
for _, pkg := range options.YarnLinks {
141141
cmd := exec.Command("yarn", "link", pkg)
142142
cmd.Dir = pt.workingDir
@@ -146,9 +146,23 @@ func (pt *PulumiTest) NewStack(t PT, stackName string, opts ...optnewstack.NewSt
146146
ptFatalF(t, "failed to link yarn package %s: %s\n%s", pkg, err, out)
147147
}
148148
}
149+
} else {
150+
projectSettings, err := stack.Workspace().ProjectSettings(pt.ctx)
151+
if err != nil {
152+
ptFatalF(t, "failed to get project settings: %s", err)
153+
}
154+
if projectSettings.Runtime.Name() == "nodejs" && len(options.YarnLinks) == 0 {
155+
if options.RequireYarnLinks == nil {
156+
ptLogF(t, "WARNING: YarnLinks were not set, but project runtime is nodejs. Module under test may not be used. Pass RequireYarnLinks(false) to silence this warning.")
157+
} else if *options.RequireYarnLinks {
158+
ptFatalF(t, "module under test may not be used: YarnLinks were not set, but project runtime is nodejs and RequireYarnLinks is true.")
159+
} else {
160+
// User decided to silence the warning explicitly by passing RequireYarnLinks(false)
161+
}
162+
}
149163
}
150164

151-
if options.GoModReplacements != nil && len(options.GoModReplacements) > 0 {
165+
if len(options.GoModReplacements) > 0 {
152166
orderedReplacements := make([]string, 0, len(options.GoModReplacements))
153167
for old := range options.GoModReplacements {
154168
orderedReplacements = append(orderedReplacements, old)

pulumitest/newStack_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,25 @@ func TestMissingProviderBinaryPath(t *testing.T) {
1919

2020
assert.True(t, tt.Failed(), "expected test to fail")
2121
}
22+
23+
func TestRequireYarnLinksEnforced(t *testing.T) {
24+
t.Parallel()
25+
26+
tt := mockT{T: t}
27+
pulumitest.NewPulumiTest(&tt, filepath.Join("testdata", "nodejs_empty"),
28+
opttest.RequireYarnLinks(true),
29+
)
30+
31+
assert.True(t, tt.Failed(), "expected test to fail")
32+
}
33+
34+
func TestRequireYarnLinksSilenced(t *testing.T) {
35+
t.Parallel()
36+
37+
tt := mockT{T: t}
38+
pulumitest.NewPulumiTest(&tt, filepath.Join("testdata", "nodejs_empty"),
39+
opttest.RequireYarnLinks(false),
40+
)
41+
42+
assert.False(t, tt.Failed(), "expected test to pass")
43+
}

pulumitest/opttest/opttest.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,13 @@ func YarnLink(packages ...string) Option {
105105
})
106106
}
107107

108+
// RequireYarnLinks specifies that the program under test requires yarn links to be specified.
109+
func RequireYarnLinks(require bool) Option {
110+
return optionFunc(func(o *Options) {
111+
o.RequireYarnLinks = &require
112+
})
113+
}
114+
108115
// GoModReplacement specifies replacements to be add to the go.mod file when running the program under test.
109116
// Each replacement is added to the go.mod file with `go mod edit -replace <replacement>` on stack creation.
110117
func GoModReplacement(packageSpecifier string, replacementPathElem ...string) Option {
@@ -175,6 +182,7 @@ type Options struct {
175182
Providers map[providers.ProviderName]ProviderConfigUnion
176183
UseAmbientBackend bool
177184
YarnLinks []string
185+
RequireYarnLinks *bool
178186
GoModReplacements map[string]string
179187
DotNetReferences map[string]string
180188
CustomEnv map[string]string
@@ -210,6 +218,7 @@ func Defaults() Option {
210218
o.Providers = make(map[providers.ProviderName]ProviderConfigUnion)
211219
o.UseAmbientBackend = false
212220
o.YarnLinks = []string{}
221+
o.RequireYarnLinks = nil
213222
o.GoModReplacements = make(map[string]string)
214223
o.DotNetReferences = make(map[string]string)
215224
o.CustomEnv = make(map[string]string)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
name: nodejs_empty
2+
runtime: nodejs
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"name": "nodejs_empty",
3+
"dependencies": {
4+
"@pulumi/pulumi": "latest"
5+
}
6+
}

pulumitest/testdata/yaml_program/Pulumi.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ outputs:
66
resources:
77
username:
88
type: random:RandomPet
9+
options:
10+
# Pin pulumi-random version
11+
version: 4.18.4

0 commit comments

Comments
 (0)