Skip to content

Conversation

brianwcook
Copy link

@brianwcook brianwcook commented Jun 12, 2025

Changes

Resolvers are awesome but can be noisy. In high traffic environments we have seen rate limiting both from registries when using the bundle resolver and from git forges when using the git resolver. This PR adds caching to the resolvers (except the cluster resolver). It is only enabled by default when 'safe' - meaning that the object was fetched by some hash / digest. Otherwise, it can be turned on with a resolver parameter.

Note

This PR is a work in progress posted for initial thoughts and feedback. It works for some cases already (git resolver) - others, maybe not.

Submitter Checklist

As the author of this PR, please check off the items in this checklist:

  • Has Docs if any changes are user facing, including updates to minimum requirements e.g. Kubernetes version bumps
  • Has Tests included if any functionality added or changed
  • pre-commit Passed
  • Follows the commit message standard
  • Meets the Tekton contributor standards (including functionality, content, code)
  • Has a kind label. You can add one by adding a comment on this PR that contains /kind <type>. Valid types are bug, cleanup, design, documentation, feature, flake, misc, question, tep
  • Release notes block below has been updated with any user facing changes (API changes, bug fixes, changes requiring upgrade notices or deprecation warnings). See some examples of good release notes.
  • Release notes contains the string "action required" if the change requires additional action from users switching to the new release

Release Notes

Remote resolver results for bundle and git resolvers which use immutable references will be cached by default for 5 minutes. User can opt-in to caching non-immutable references or disable caching entirely. The default caching mode (auto) should be safe and entirely transparent for existing users.

@tekton-robot tekton-robot added release-note-none Denotes a PR that doesnt merit a release note. do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. labels Jun 12, 2025
Copy link

linux-foundation-easycla bot commented Jun 12, 2025

CLA Signed

The committers listed above are authorized under a signed CLA.

@tekton-robot tekton-robot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Jun 12, 2025
@tekton-robot
Copy link
Collaborator

The following is the coverage report on the affected files.
Say /test pull-tekton-pipeline-go-coverage-df to re-run this coverage report

File Old Coverage New Coverage Delta
pkg/remoteresolution/cache/cache.go Do not exist 86.4%
pkg/remoteresolution/resolver/bundle/resolver.go 81.8% 62.1% -19.7
pkg/remoteresolution/resolver/http/resolver.go 88.9% 78.1% -10.8
pkg/remoteresolution/resolver/hub/resolver.go 50.0% 57.1% 7.1
pkg/resolution/resolver/framework/cache.go Do not exist 29.4%

@tekton-robot
Copy link
Collaborator

The following is the coverage report on the affected files.
Say /test pull-tekton-pipeline-go-coverage-df to re-run this coverage report

File Old Coverage New Coverage Delta
pkg/remoteresolution/cache/cache.go Do not exist 86.4%
pkg/remoteresolution/resolver/bundle/resolver.go 81.8% 62.1% -19.7
pkg/remoteresolution/resolver/http/resolver.go 88.9% 78.1% -10.8
pkg/remoteresolution/resolver/hub/resolver.go 50.0% 57.1% 7.1
pkg/resolution/resolver/bundle/params.go 87.9% 88.2% 0.4

@tekton-robot
Copy link
Collaborator

The following is the coverage report on the affected files.
Say /test pull-tekton-pipeline-go-coverage-df to re-run this coverage report

File Old Coverage New Coverage Delta
pkg/remoteresolution/cache/cache.go Do not exist 86.4%
pkg/remoteresolution/resolver/bundle/resolver.go 81.8% 82.9% 1.1
pkg/remoteresolution/resolver/http/resolver.go 88.9% 78.1% -10.8
pkg/remoteresolution/resolver/hub/resolver.go 50.0% 57.1% 7.1
pkg/resolution/resolver/bundle/bundle.go 71.1% 71.4% 0.4
pkg/resolution/resolver/bundle/params.go 87.9% 86.1% -1.8

@tekton-robot tekton-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Jun 13, 2025
@tekton-robot
Copy link
Collaborator

The following is the coverage report on the affected files.
Say /test pull-tekton-pipeline-go-coverage-df to re-run this coverage report

File Old Coverage New Coverage Delta
pkg/remoteresolution/cache/cache.go Do not exist 86.4%
pkg/remoteresolution/resolver/bundle/resolver.go 81.8% 82.9% 1.1
pkg/remoteresolution/resolver/git/resolver.go 82.4% 65.0% -17.4
pkg/remoteresolution/resolver/http/resolver.go 88.9% 78.1% -10.8
pkg/remoteresolution/resolver/hub/resolver.go 50.0% 57.1% 7.1
pkg/resolution/resolver/bundle/bundle.go 71.1% 71.4% 0.4
pkg/resolution/resolver/bundle/params.go 87.9% 86.1% -1.8

@tekton-robot tekton-robot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Jun 13, 2025
@tekton-robot
Copy link
Collaborator

The following is the coverage report on the affected files.
Say /test pull-tekton-pipeline-go-coverage-df to re-run this coverage report

File Old Coverage New Coverage Delta
pkg/remoteresolution/cache/cache.go Do not exist 58.3%
pkg/remoteresolution/resolver/bundle/resolver.go 81.8% 83.7% 1.9
pkg/remoteresolution/resolver/git/resolver.go 82.4% 83.9% 1.5
pkg/resolution/resolver/bundle/bundle.go 71.1% 71.4% 0.4
pkg/resolution/resolver/bundle/params.go 87.9% 86.1% -1.8
pkg/resolution/resolver/git/resolver.go 84.9% 84.3% -0.6

@tekton-robot
Copy link
Collaborator

The following is the coverage report on the affected files.
Say /test pull-tekton-pipeline-go-coverage-df to re-run this coverage report

File Old Coverage New Coverage Delta
pkg/remoteresolution/cache/cache.go Do not exist 58.3%
pkg/remoteresolution/resolver/bundle/resolver.go 81.8% 83.7% 1.9
pkg/remoteresolution/resolver/git/resolver.go 82.4% 83.9% 1.5
pkg/resolution/resolver/bundle/bundle.go 71.1% 71.4% 0.4
pkg/resolution/resolver/bundle/params.go 87.9% 86.1% -1.8
pkg/resolution/resolver/git/resolver.go 84.9% 84.3% -0.6

@tekton-robot
Copy link
Collaborator

The following is the coverage report on the affected files.
Say /test pull-tekton-pipeline-go-coverage-df to re-run this coverage report

File Old Coverage New Coverage Delta
pkg/remoteresolution/cache/cache.go Do not exist 58.3%
pkg/remoteresolution/resolver/bundle/resolver.go 81.8% 83.7% 1.9
pkg/remoteresolution/resolver/git/resolver.go 82.4% 83.9% 1.5
pkg/resolution/resolver/bundle/bundle.go 71.1% 71.4% 0.4
pkg/resolution/resolver/bundle/params.go 87.9% 86.1% -1.8
pkg/resolution/resolver/git/resolver.go 84.9% 84.3% -0.6

@brianwcook
Copy link
Author

/kind feature

@tekton-robot tekton-robot added the kind/feature Categorizes issue or PR as related to a new feature. label Jun 14, 2025
@tekton-robot
Copy link
Collaborator

The following is the coverage report on the affected files.
Say /test pull-tekton-pipeline-go-coverage-df to re-run this coverage report

File Old Coverage New Coverage Delta
pkg/remoteresolution/cache/cache.go Do not exist 58.3%
pkg/remoteresolution/resolver/bundle/resolver.go 81.8% 83.7% 1.9
pkg/remoteresolution/resolver/git/resolver.go 82.4% 83.9% 1.5
pkg/resolution/resolver/bundle/bundle.go 71.1% 71.4% 0.4
pkg/resolution/resolver/bundle/params.go 87.9% 86.1% -1.8
pkg/resolution/resolver/git/resolver.go 84.9% 84.3% -0.6

@tekton-robot tekton-robot removed the size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. label Jun 15, 2025
@tekton-robot
Copy link
Collaborator

The following is the coverage report on the affected files.
Say /test pull-tekton-pipeline-go-coverage-df to re-run this coverage report

File Old Coverage New Coverage Delta
pkg/apis/config/resolver/feature_flags.go 84.0% 84.6% 0.6
pkg/remoteresolution/cache/annotated_resource.go Do not exist 100.0%
pkg/remoteresolution/cache/cache.go Do not exist 79.7%
pkg/remoteresolution/cache/injection/cache.go Do not exist 88.0%
pkg/remoteresolution/resolver/bundle/resolver.go 81.8% 95.8% 14.0
pkg/remoteresolution/resolver/cluster/resolver.go 81.8% 100.0% 18.2
pkg/remoteresolution/resolver/framework/cache.go Do not exist 96.6%
pkg/remoteresolution/resolver/framework/reconciler.go 75.3% 73.8% -1.6
pkg/remoteresolution/resolver/git/resolver.go 82.4% 86.5% 4.2
pkg/remoteresolution/resolver/http/resolver.go 88.9% 100.0% 11.1
pkg/resolution/resolver/bundle/bundle.go 71.1% 71.4% 0.4
pkg/resolution/resolver/bundle/params.go 87.9% 86.1% -1.8
pkg/resolution/resolver/cluster/resolver.go 80.4% 79.9% -0.6
pkg/resolution/resolver/git/resolver.go 84.9% 84.3% -0.6

@tekton-robot
Copy link
Collaborator

The following is the coverage report on the affected files.
Say /test pull-tekton-pipeline-go-coverage-df to re-run this coverage report

File Old Coverage New Coverage Delta
pkg/apis/config/resolver/feature_flags.go 84.0% 84.6% 0.6
pkg/remoteresolution/cache/annotated_resource.go Do not exist 100.0%
pkg/remoteresolution/cache/cache.go Do not exist 79.7%
pkg/remoteresolution/cache/injection/cache.go Do not exist 88.0%
pkg/remoteresolution/resolver/bundle/resolver.go 81.8% 95.8% 14.0
pkg/remoteresolution/resolver/cluster/resolver.go 81.8% 100.0% 18.2
pkg/remoteresolution/resolver/framework/cache.go Do not exist 96.6%
pkg/remoteresolution/resolver/framework/reconciler.go 75.3% 73.8% -1.6
pkg/remoteresolution/resolver/git/resolver.go 82.4% 86.5% 4.2
pkg/remoteresolution/resolver/http/resolver.go 88.9% 100.0% 11.1
pkg/resolution/resolver/bundle/bundle.go 71.1% 71.4% 0.4
pkg/resolution/resolver/bundle/params.go 87.9% 86.1% -1.8
pkg/resolution/resolver/cluster/resolver.go 80.4% 79.9% -0.6
pkg/resolution/resolver/git/resolver.go 84.9% 84.3% -0.6

@brianwcook
Copy link
Author

/retest

brianwcook and others added 19 commits September 5, 2025 10:44
This commit adds caching for bundle and git resolvers to reduce
chances of being rate limited by registries and git forges.

- Add cache interface and in-memory implementation
- Add cache configuration options to docs
- Add a simple 'always on or off' option for cluster resolver
- Add documentation for cache configuration

Signed-off-by: Brian Cook <[email protected]>
- Remove dead GetGlobalCache function and globalCache variable
- Update tests to use dependency injection cache instead of global cache
- Add cache clearing in test setup to ensure test isolation
- Fix all GetGlobalCache references in cache_test.go and resolver tests

This resolves the shared cache state issue that was causing e2e test
failures (TestPropagatedParams, TestLargerResultsSidecarLogs) by ensuring
each test gets a clean cache state.
- Add cache_test.go with 100% coverage of cache.go functions
- Test ShouldUseCache with all priority levels and cache modes
- Test GetSystemDefaultCacheMode for different resolver types
- Test ValidateCacheMode with valid/invalid inputs
- Test cache constants validation
- Includes 20+ test cases covering edge cases and error conditions

This resolves CI coverage issue for pkg/remoteresolution/resolver/framework/cache.go
- Replace nil, nil return with proper sentinel error
- Add errors import to support error creation
- Resolves nilnil linter warning in mockCacheAwareResolver.Resolve

The mock method was never called in tests but needed proper error handling.
…ve cache API

make GenerateCacheKey private and improve cache API
Fix cache unit tests for private generateCacheKey function
make generateCacheKey private
cache API refactoring
move unit tests
Implement RunCacheOperations
Add comprehensive package-scoped unit tests for generateCacheKey function
Fix bundle resolver tests: restore original tests + add cache tests
Fix bundle resolver compatibility with existing tests
Implement Interface Simplification (ImmutabilityChecker)
Remove duplicate IsOCIPullSpecByDigest function
Move cache decision tests to framework
Fix method signature consistency
Complete Code Style & Cleanup
make GenerateCacheKey private and improve cache API
Fix cache unit tests for private generateCacheKey function
make generateCacheKey private
cache API refactoring
move unit tests
Implement RunCacheOperations
Add comprehensive package-scoped unit tests for generateCacheKey function
Fix bundle resolver tests: restore original tests + add cache tests
Fix bundle resolver compatibility with existing tests
Implement Interface Simplification (ImmutabilityChecker)
Remove duplicate IsOCIPullSpecByDigest function
Move cache decision tests to framework
Fix method signature consistency
Complete Code Style & Cleanup
- Add missing pipelinerun-with-task-timeout-override.yaml example
- Increase timeout from 20s to 45s to account for pod startup overhead
- Provides 35s buffer for Kubernetes pod initialization + 10s task execution
- Maintains test intent (TaskRunSpecs override Pipeline task timeouts)
- Eliminates timing-related flakiness in CI environments

Resolves intermittent test failures in examples test matrix where
pod startup overhead (17s observed) exceeded the 20s timeout window.
- Add FeatureFlags.AnyResolverEnabled() helper function
- Implement lazy cache initialization with sync.Once
- Cache only loads when any resolver is enabled
- RunCacheOperations handles nil cache gracefully
- Remove extra blank lines in resolver_integration_test.go
- Fix whitespace in conversion_test.go
- Fix trailing space in start_time_test.go comment
@tekton-robot
Copy link
Collaborator

The following is the coverage report on the affected files.
Say /test pull-tekton-pipeline-go-coverage-df to re-run this coverage report

File Old Coverage New Coverage Delta
pkg/apis/config/resolver/feature_flags.go 84.0% 84.6% 0.6
pkg/remoteresolution/cache/annotated_resource.go Do not exist 100.0%
pkg/remoteresolution/cache/cache.go Do not exist 79.7%
pkg/remoteresolution/cache/injection/cache.go Do not exist 88.0%
pkg/remoteresolution/resolver/bundle/resolver.go 81.8% 95.8% 14.0
pkg/remoteresolution/resolver/cluster/resolver.go 81.8% 100.0% 18.2
pkg/remoteresolution/resolver/framework/cache.go Do not exist 96.6%
pkg/remoteresolution/resolver/framework/reconciler.go 75.3% 73.8% -1.6
pkg/remoteresolution/resolver/git/resolver.go 82.4% 86.5% 4.2
pkg/remoteresolution/resolver/http/resolver.go 88.9% 100.0% 11.1
pkg/resolution/resolver/bundle/bundle.go 71.1% 71.4% 0.4
pkg/resolution/resolver/bundle/params.go 87.9% 86.1% -1.8
pkg/resolution/resolver/cluster/resolver.go 80.4% 79.9% -0.6
pkg/resolution/resolver/git/resolver.go 84.9% 84.3% -0.6

@waveywaves
Copy link
Member

/retest

@waveywaves
Copy link
Member

waveywaves commented Sep 10, 2025

@brianwcook can you squash all the commits into one while following the commit message guidelines in the repository as well :) that would be very helpful, thank you. maybe we can wait for that till after all the comments and reviews are resolved

@aThorp96
Copy link
Member

/cc @twoGiants it looks like this is ready for re-review. I'm going to try and make some time to work through it this week, but since you requested changes I think you'll need to review again as well

@twoGiants
Copy link
Member

... maybe we can wait for that till after all the comments and reviews are resolved

@waveywaves @brianwcook yes please 🥺 😸 👍

/cc @twoGiants it looks like this is ready for re-review. I'm going to try and make some time to work through it this week, but since you requested changes I think you'll need to review again as well

@aThorp96 yesssss! Looking forward to it.

@brianwcook can I re-review? Just let me know when its ready and thank you for the good work 🥇 !

Copy link
Member

@vdemeester vdemeester left a comment

Choose a reason for hiding this comment

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

  • If the admin enable cache after installation, do we have to restart the controller or is it dynamically switch on / off (like other features) ?
  • No need to change copyright dates for existing files

This still needs a lot of work and review comment to take into acount. Given the amount of time we spend for reviewing this, I really think one of us should carry it on.

}

// createContextWithResolverConfig creates a test context with resolver configuration
func createContextWithResolverConfig(t *testing.T, anyResolverEnabled bool) context.Context {
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this param named differently ? it's only setting the git resolver on or off.


// GetCacheConfigName returns the name of the cache configuration ConfigMap.
// This can be overridden via the CONFIG_RESOLVER_CACHE_NAME environment variable.
func GetCacheConfigName() string {
Copy link
Member

Choose a reason for hiding this comment

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

Interesting. I think there is, on other part where we look for a configmap, some env var like this as well. So maybe it should be there, but used also outside of the tests ?

func (c *ResolverCache) Add(resolverType string, params []pipelinev1.Param, resource resolutionframework.ResolvedResource) resolutionframework.ResolvedResource {
key := generateCacheKey(resolverType, params)

if c.logger != nil {
Copy link
Member

Choose a reason for hiding this comment

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

In almost any places in the code, we don't check if the logger we use is nil, it is assumed it is always set.

Comment on lines +214 to +219
for i, val := range arrayVals {
if i > 0 {
paramStr += ","
}
paramStr += val
}
Copy link
Member

Choose a reason for hiding this comment

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

we could use strings.Join here I think.

})
}

func withCacheFromConfig(ctx context.Context, cfg *rest.Config) context.Context {
Copy link
Member

Choose a reason for hiding this comment

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

the cfg parameter is not used, we can remove it.

@@ -1,5 +1,5 @@
/*
Copyright 2024 The Tekton Authors
Copy link
Member

Choose a reason for hiding this comment

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

No need to touch this.

LabelValueBundleResolverType string = "bundles"

// BundleResolverName is the name that the bundle resolver should be associated with.
BundleResolverName = "bundleresolver"
Copy link
Member

Choose a reason for hiding this comment

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

I am not sure why it should be made deprecated ? The bundle resolver is here to stay (the bundle field is deprecated, but not the bundles nor the resolver).

I also don't see any reason to change this if it causes some issues (metrics, workqueue, ...). If we do change it, I'd rather do it on its own PR, etc..

return nil, errors.New("the Resolve method has not been implemented.")

// Get the resolve function - default to bundleresolution.ResolveRequest if not set
resolveFunc := r.resolveRequestFunc
Copy link
Member

Choose a reason for hiding this comment

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

How can r.resolveRequestFunc be set ? Given that we have another return in the if r.useCache(.., I don't really understand this change. We could have a simpler implementation, isn't it ?

(and it seems to be what is done in other resolvers as well)

Comment on lines -47 to 54
// associated with.
func (r *FakeResolver) GetName(_ context.Context) string {
func (r *FakeResolver) GetName(ctx context.Context) string {
return framework.FakeResolverName
}

// GetSelector returns the labels that resource requests are required to have for
// the fake resolver to process them.
func (r *FakeResolver) GetSelector(_ context.Context) map[string]string {
func (r *FakeResolver) GetSelector(ctx context.Context) map[string]string {
return map[string]string{
Copy link
Member

Choose a reason for hiding this comment

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

Any reason for those changes ? ctx not being used, it can be anynomized.

func (r *Resolver) Validate(ctx context.Context, req *v1beta1.ResolutionRequestSpec) error {
if len(req.Params) > 0 {
return git.ValidateParams(ctx, req.Params)
return git.ValidateParams(ctx, req.Params)
Copy link
Member

Choose a reason for hiding this comment

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

Is git the package itself ? If yes, it is not required here, I am amazed that go doesn't complain about it even.

Same below and in the tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/feature Categorizes issue or PR as related to a new feature. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

6 participants