Skip to content

Fix 5301: Build dependencies for sync inherited from required artifacts; cache build dependencies between devloops #5614

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 5, 2021

Conversation

gsquared94
Copy link
Contributor

@gsquared94 gsquared94 commented Mar 29, 2021

Fixes: #5301 #5522
Related: #5374

Description

Currently the build dependencies for any artifact are evaluated on every file change trigger. In #5301, we need to recursively evaluate the build dependencies for all artifacts in the transitive closure of artifacts reachable from the target via its artifact-dependencies list. For the worst case contrived example, there could be an exponential number of build dependency evaluations for any artifact in a single devloop. So we additionally introduce a cache that gets cleared on the start of every devloop. This ensures that for the duration of a single devloop the build dependencies won't be reevaluated.

Can be tested by running against this repro for 5301

PS: We could optimize further by resetting the cache only when the FS notify trigger is of type file added, since file modification or deletion won't change the result of the build dependencies from the previous devloop. However, that wouldn't work with polling or manual trigger types.

@codecov
Copy link

codecov bot commented Mar 29, 2021

Codecov Report

Merging #5614 (a078bc9) into master (2c10abe) will decrease coverage by 0.02%.
The diff coverage is 74.50%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #5614      +/-   ##
==========================================
- Coverage   70.66%   70.64%   -0.03%     
==========================================
  Files         408      408              
  Lines       15559    15581      +22     
==========================================
+ Hits        10995    11007      +12     
- Misses       3757     3764       +7     
- Partials      807      810       +3     
Impacted Files Coverage Δ
pkg/skaffold/build/gcb/cloud_build.go 0.70% <0.00%> (ø)
pkg/skaffold/diagnose/diagnose.go 14.70% <0.00%> (-0.45%) ⬇️
pkg/skaffold/runner/runner.go 0.00% <ø> (ø)
pkg/skaffold/runner/dev.go 72.67% <50.00%> (-1.11%) ⬇️
pkg/skaffold/build/dependencies.go 17.77% <53.33%> (+17.77%) ⬆️
pkg/skaffold/runner/new.go 62.56% <94.11%> (+0.63%) ⬆️
pkg/skaffold/build/docker/types.go 100.00% <100.00%> (ø)
pkg/skaffold/build/gcb/types.go 53.84% <100.00%> (+3.84%) ⬆️
pkg/skaffold/build/local/types.go 86.00% <100.00%> (+0.28%) ⬆️
pkg/skaffold/runner/builder.go 72.72% <100.00%> (+1.29%) ⬆️
... and 2 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2c10abe...a078bc9. Read the comment docs.

@@ -62,9 +62,12 @@ func NewForConfig(runCtx *runcontext.RunContext) (*SkaffoldRunner, error) {
}

store := build.NewArtifactStore()
graph := build.ToArtifactGraph(runCtx.Artifacts())
depsResolver := build.GetDependenciesResolver(runCtx, store, graph)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The depsResolver contains the store and bCtx contains a reference to both store and depResolver
Can we make it simpler by adding the method GetArtifactStore on DependencyResolver interface vs on bCtx?

IIUC, right now

                      <Runner>
                           |
             --------------------
             |                   |
  <ArtifactStore>        <DependencyResolver>
             |                    ^
              --------------------|

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The methods are somewhat unrelated though: DependencyResolver is actually the source-dependency-resolver which returns the list of files to watch for any artifact. ArtifactStore returns the latest tag for any built image. They could be under a BuildContext object but there's no good place to put this object without running into circular dependencies trying to import it across the different build env and the different builder implementations.
Right now there is a single buildCtx struct that implements both these interfaces but it's local to the runner package whereas the interface methods are exposed in the Config parameter of every builder setup.

I'll take another stab at it to merge these constructs.

also cc @briandealwis for his similar comments.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Methods added to BuildContext. Kept ArtifactStore and SourceDependencies as separate interfaces still.

Copy link
Member

@briandealwis briandealwis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High level comments:

  • I think the DependencyResolver would be better named to indicate that it is a cache: DependencyCache
  • I find myself confused by dependency-as-artifact-dependency and dependency-as-artifact-sources. I'd be inclined to rename dependency-as-artifact-dependency to requires? Or otherwise making explicitly indicating dependency-as-artifact-sources as source-dependencies
  • picking up on @tejal29's comment: it would seem to make sense to have a build-context that included the dependencies cache and artifact store

var getDependenciesFunc = dependenciesForSingleArtifact

type DependencyResolver interface {
DependenciesForArtifact(ctx context.Context, a *latest.Artifact) ([]string, error)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does *latest.Artifact need to be a pointer? Do we do anything destructive?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The convention in our codebase seems to be to pass around pointers for all SkaffoldConfig objects so I followed the same. Otherwise there's no need for this to be a pointer.

@gsquared94
Copy link
Contributor Author

@tejal29 @briandealwis I've implemented the builderCtx suggestion in #5623

@kervel
Copy link

kervel commented Apr 2, 2021

just for info: i'm now using this PR instead of the old one on our setup and everything works fine!

cache build dependencies between devloops
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

skaffold dependency resolving (for file sync) is not recursive
4 participants