diff --git a/go.mod b/go.mod index f353f5e97b..621741c74d 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/ghodss/yaml v1.0.0 github.com/go-logr/logr v1.2.3 github.com/gogo/protobuf v1.3.2 + github.com/golang/protobuf v1.5.2 github.com/google/go-cmp v0.5.8 github.com/google/uuid v1.3.0 github.com/google/wire v0.5.0 @@ -143,7 +144,6 @@ require ( github.com/gogo/googleapis v1.4.0 // indirect github.com/golang-jwt/jwt/v4 v4.0.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect github.com/google/btree v1.0.1 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect diff --git a/internal/tiltfile/tiltextension/plugin_test.go b/internal/tiltfile/tiltextension/plugin_test.go index 2b1851265b..e5bd69a414 100644 --- a/internal/tiltfile/tiltextension/plugin_test.go +++ b/internal/tiltfile/tiltextension/plugin_test.go @@ -163,6 +163,34 @@ printFoo() f.assertLoadRecorded(res, "my-extension") } +func TestLoadedExtensionTwiceDifferentFiles(t *testing.T) { + if runtime.GOOS == "windows" { + // We don't want to have to bother with file:// escaping on windows. + // The repo reconciler already tests this. + t.Skip() + } + + f := newExtensionFixture(t) + + f.tmp.WriteFile(filepath.Join("my-custom-repo", "my-custom-path", "Tiltfile"), libText) + + subfileContent := fmt.Sprintf(` +v1alpha1.extension_repo(name='my-extension-repo', url='file://%s/my-custom-repo') +v1alpha1.extension(name='my-extension', repo_name='my-extension-repo', repo_path='my-custom-path') +load('ext://my-extension', 'printFoo') +printFoo() +`, f.tmp.Path()) + + f.skf.File("Tiltfile.a", subfileContent) + f.skf.File("Tiltfile.b", subfileContent) + f.tiltfile(` +include('Tiltfile.a') +include('Tiltfile.b') +`) + res := f.assertExecOutput("foo\nfoo") + f.assertLoadRecorded(res, "my-extension") +} + type extensionFixture struct { t *testing.T skf *starkit.Fixture diff --git a/internal/tiltfile/v1alpha1/plugin.go b/internal/tiltfile/v1alpha1/plugin.go index 94f97bc56b..c716ac4aca 100644 --- a/internal/tiltfile/v1alpha1/plugin.go +++ b/internal/tiltfile/v1alpha1/plugin.go @@ -10,6 +10,7 @@ import ( "github.com/tilt-dev/tilt/internal/controllers/apicmp" "github.com/tilt-dev/tilt/internal/controllers/apiset" "github.com/tilt-dev/tilt/internal/tiltfile/starkit" + "github.com/tilt-dev/tilt/pkg/apis/core/v1alpha1" ) // Defines starlark functions that register API objects @@ -47,8 +48,13 @@ func (p Plugin) register(t *starlark.Thread, obj apiset.Object) (starlark.Value, typedSet := set.GetOrCreateTypedSet(obj) name := obj.GetName() existing, exists := typedSet[name] - if exists && !apicmp.DeepEqual(obj, existing) { - return set, fmt.Errorf("%s %q already registered", obj.GetGroupVersionResource().Resource, name) + if exists { + // tiltextension adds this for extensions, but new objects will not + // have this annotation yet, so delete for comparison + delete(existing.GetAnnotations(), v1alpha1.AnnotationManagedBy) + if !apicmp.DeepEqual(obj, existing) { + return set, fmt.Errorf("%s %q already registered", obj.GetGroupVersionResource().Resource, name) + } } typedSet[name] = obj