From bc8e94fb0cbadd4d56c81a74017b6cc938acb4c4 Mon Sep 17 00:00:00 2001 From: Matt Toohey Date: Fri, 11 Oct 2024 10:11:19 +1100 Subject: [PATCH] engine responds to invalidated dependencies --- internal/buildengine/build.go | 8 ++++++++ internal/buildengine/engine.go | 10 +++++++++- internal/buildengine/languageplugin/plugin.go | 2 +- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/internal/buildengine/build.go b/internal/buildengine/build.go index 7a629b369a..7a2ca68a31 100644 --- a/internal/buildengine/build.go +++ b/internal/buildengine/build.go @@ -17,9 +17,13 @@ import ( "github.com/TBD54566975/ftl/internal/schema" ) +var invalidateDependenciesError = errors.New("dependencies need to be updated") + // Build a module in the given directory given the schema and module config. // // A lock file is used to ensure that only one build is running at a time. +// +// Returns invalidateDependenciesError if the build failed due to a change in dependencies. func build(ctx context.Context, plugin languageplugin.LanguagePlugin, projectRootDir string, bctx languageplugin.BuildContext, buildEnv []string, devMode bool) (moduleSchema *schema.Module, deploy []string, err error) { logger := log.FromContext(ctx).Module(bctx.Config.Module).Scope("build") ctx = log.ContextWithLogger(ctx, logger) @@ -46,6 +50,10 @@ func handleBuildResult(ctx context.Context, c moduleconfig.ModuleConfig, eitherR result = eitherResult.Get() } + if result.InvalidateDependencies { + return nil, nil, invalidateDependenciesError + } + var errs []error for _, e := range result.Errors { if e.Level == builderrors.WARN { diff --git a/internal/buildengine/engine.go b/internal/buildengine/engine.go index f38b652c74..b90aa67d88 100644 --- a/internal/buildengine/engine.go +++ b/internal/buildengine/engine.go @@ -633,7 +633,6 @@ func (e *Engine) BuildAndDeploy(ctx context.Context, replicas int32, waitForDepl type buildCallback func(ctx context.Context, module Module) error func (e *Engine) buildWithCallback(ctx context.Context, callback buildCallback, moduleNames ...string) error { - if len(moduleNames) == 0 { e.moduleMetas.Range(func(name string, meta moduleMeta) bool { moduleNames = append(moduleNames, name) @@ -820,6 +819,15 @@ func (e *Engine) build(ctx context.Context, moduleName string, builtModules map[ }, e.buildEnv, e.devMode) if err != nil { terminal.UpdateModuleState(ctx, moduleName, terminal.BuildStateFailed) + if errors.Is(err, invalidateDependenciesError) { + go func() { + logger := log.FromContext(ctx) + err := e.BuildAndDeploy(ctx, 1, true, moduleName) + e.reportBuildFailed(err) + terminal.UpdateModuleState(ctx, moduleName, terminal.BuildStateFailed) + logger.Errorf(err, "Build and deploy failed for module %q", moduleName) + }() + } return err } // update files to deploy diff --git a/internal/buildengine/languageplugin/plugin.go b/internal/buildengine/languageplugin/plugin.go index b7e7fe7300..83188c3e42 100644 --- a/internal/buildengine/languageplugin/plugin.go +++ b/internal/buildengine/languageplugin/plugin.go @@ -31,7 +31,7 @@ type BuildResult struct { // Files to deploy, relative to the module config's DeployDir Deploy []string - // Docs + // Whether the module needs to recalculate its dependencies InvalidateDependencies bool }