Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
2778bf9
feat: implement caching for bundle, git and cluster resolvers
brianwcook Jul 22, 2025
d73b4c0
run codegen
brianwcook Aug 4, 2025
b5827c9
clear cache in test setup
brianwcook Aug 4, 2025
1535611
revert unneeded changes
brianwcook Aug 4, 2025
e5bd298
Fix resolver cache regression and remove GetGlobalCache
brianwcook Aug 4, 2025
bdb7c45
Update pkg/remoteresolution/resolver/framework/reconciler.go
brianwcook Aug 16, 2025
74c6f9a
Add comprehensive unit tests for resolver framework cache
brianwcook Aug 5, 2025
eae9119
Fix linting issue in cache_test.go
brianwcook Aug 5, 2025
f6d00d5
updated copyright year to 2025
brianwcook Aug 16, 2025
5a845d2
revert hub resolver, fix bundle api (name)
brianwcook Aug 16, 2025
caa6632
remove error return from generateCacheKey
brianwcook Aug 16, 2025
4a362d0
Implement twoGiants feedback: make GenerateCacheKey private and impro…
brianwcook Aug 16, 2025
0850727
many changes to addreess review feedback
brianwcook Aug 16, 2025
f5d402b
Add comprehensive unit tests for cache injection package
brianwcook Aug 18, 2025
55c16ee
Fix flaky task timeout override test
brianwcook Aug 19, 2025
0b9dd7a
Fix linter errors from CI
brianwcook Aug 20, 2025
fed67d7
Implement conditional cache initialization
brianwcook Aug 20, 2025
a3078a6
add webhook readiness checks
brianwcook Aug 20, 2025
a6bd055
Fix formatting issues (gofmt/goimports)
brianwcook Sep 5, 2025
4259a12
refactor resolver cache to improve encapsulation and reduce duplication
waveywaves Sep 29, 2025
e325e6f
add comprehensive cache key validation tests
waveywaves Sep 29, 2025
c5023e5
document dynamic cache configuration behavior
waveywaves Sep 29, 2025
f316e07
fix framework tests after cache key privatization
waveywaves Sep 29, 2025
05adc2c
make cache annotation constants private
waveywaves Sep 30, 2025
88e5b81
simplify validatecachemode to return only error
waveywaves Sep 30, 2025
f3f10f9
fix gofmt formatting issues
waveywaves Sep 30, 2025
e6e935b
fix copyright years for existing files
waveywaves Sep 30, 2025
5404c19
remove unused public constants and functions
waveywaves Sep 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
*.dylib
*.dll

# Go test binaries
*.test

# Fortran module files
*.smod

Expand Down
1 change: 1 addition & 0 deletions .serena/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/cache
67 changes: 67 additions & 0 deletions .serena/project.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# language of the project (csharp, python, rust, java, typescript, go, cpp, or ruby)
# * For C, use cpp
# * For JavaScript, use typescript
# Special requirements:
# * csharp: Requires the presence of a .sln file in the project folder.
language: go

# whether to use the project's gitignore file to ignore files
# Added on 2025-04-07
ignore_all_files_in_gitignore: true
# list of additional paths to ignore
# same syntax as gitignore, so you can use * and **
# Was previously called `ignored_dirs`, please update your config if you are using that.
# Added (renamed) on 2025-04-07
ignored_paths: []

# whether the project is in read-only mode
# If set to true, all editing tools will be disabled and attempts to use them will result in an error
# Added on 2025-04-18
read_only: false

# list of tool names to exclude. We recommend not excluding any tools, see the readme for more details.
# Below is the complete list of tools for convenience.
# To make sure you have the latest list of tools, and to view their descriptions,
# execute `uv run scripts/print_tool_overview.py`.
#
# * `activate_project`: Activates a project by name.
# * `check_onboarding_performed`: Checks whether project onboarding was already performed.
# * `create_text_file`: Creates/overwrites a file in the project directory.
# * `delete_lines`: Deletes a range of lines within a file.
# * `delete_memory`: Deletes a memory from Serena's project-specific memory store.
# * `execute_shell_command`: Executes a shell command.
# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced.
# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type).
# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type).
# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes.
# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file.
# * `initial_instructions`: Gets the initial instructions for the current project.
# Should only be used in settings where the system prompt cannot be set,
# e.g. in clients you have no control over, like Claude Desktop.
# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol.
# * `insert_at_line`: Inserts content at a given line in a file.
# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol.
# * `list_dir`: Lists files and directories in the given directory (optionally with recursion).
# * `list_memories`: Lists memories in Serena's project-specific memory store.
# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building).
# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context).
# * `read_file`: Reads a file within the project directory.
# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store.
# * `remove_project`: Removes a project from the Serena configuration.
# * `replace_lines`: Replaces a range of lines within a file with new content.
# * `replace_symbol_body`: Replaces the full definition of a symbol.
# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen.
# * `search_for_pattern`: Performs a search for a pattern in the project.
# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase.
# * `switch_modes`: Activates modes by providing a list of their names
# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information.
# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task.
# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed.
# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store.
excluded_tools: []

# initial prompt for the project. It will always be given to the LLM upon activating the project
# (contrary to the memories, which are loaded on demand).
initial_prompt: ""

project_name: "pipeline2"
11 changes: 11 additions & 0 deletions docs/bundle-resolver.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ This Resolver responds to type `bundles`.
| `bundle` | The bundle url pointing at the image to fetch | `gcr.io/tekton-releases/catalog/upstream/golang-build:0.1` |
| `name` | The name of the resource to pull out of the bundle | `golang-build` |
| `kind` | The resource kind to pull out of the bundle | `task` |
| `cache` | Controls caching behavior for the resolved resource | `always`, `never`, `auto` |

## Requirements

Expand All @@ -45,6 +46,16 @@ for the name, namespace and defaults that the resolver ships with.
| `backoff-cap` | The maxumum backoff duration. If reached, remaining steps are zeroed.| `10s`, `20s` |
| `default-kind` | The default layer kind in the bundle image. | `task`, `pipeline` |

### Caching Options

The bundle resolver supports caching of resolved resources to improve performance. The caching behavior can be configured using the `cache` option:

| Cache Value | Description |
|-------------|-------------|
| `always` | Always cache resolved resources. This is the most aggressive caching strategy and will cache all resolved resources regardless of their source. |
| `never` | Never cache resolved resources. This disables caching completely. |
| `auto` | Caching will only occur for bundles pulled by digest. (default) |

## Usage

### Task Resolution
Expand Down
56 changes: 56 additions & 0 deletions docs/cluster-resolver.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@ This Resolver responds to type `cluster`.
| `kind` | The kind of resource to fetch. | `task`, `pipeline`, `stepaction` |
| `name` | The name of the resource to fetch. | `some-pipeline`, `some-task` |
| `namespace` | The namespace in the cluster containing the resource. | `default`, `other-namespace` |
| `cache` | Optional cache mode for the resolver. | `always`, `never`, `auto` |

### Cache Parameter

The `cache` parameter controls whether the cluster resolver caches resolved resources:

| Cache Mode | Description |
|------------|-------------|
| `always` | Always cache the resolved resource, regardless of whether it has an immutable reference. |
| `never` | Never cache the resolved resource. |
| `auto` | **Cluster resolver behavior**: Never cache (cluster resources lack immutable references). |
| (not specified) | **Default behavior**: Never cache (same as `auto` for cluster resolver). |

**Note**: The cluster resolver only caches when `cache: always` is explicitly specified. This is because cluster resources (Tasks, Pipelines, etc.) do not have immutable references like Git commit hashes or bundle digests, making automatic caching unreliable.

## Requirements

Expand Down Expand Up @@ -63,6 +77,48 @@ spec:
value: namespace-containing-task
```

### Task Resolution with Caching

```yaml
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
name: remote-task-reference-cached
spec:
taskRef:
resolver: cluster
params:
- name: kind
value: task
- name: name
value: some-task
- name: namespace
value: namespace-containing-task
- name: cache
value: always
```

### Task Resolution without Caching

```yaml
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
name: remote-task-reference-no-cache
spec:
taskRef:
resolver: cluster
params:
- name: kind
value: task
- name: name
value: some-task
- name: namespace
value: namespace-containing-task
- name: cache
value: never
```

### StepAction Resolution

```yaml
Expand Down
11 changes: 11 additions & 0 deletions docs/git-resolver.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ This Resolver responds to type `git`.
| `pathInRepo` | Where to find the file in the repo. | `task/golang-build/0.3/golang-build.yaml` |
| `serverURL` | An optional server URL (that includes the https:// prefix) to connect for API operations | `https:/github.mycompany.com` |
| `scmType` | An optional SCM type to use for API operations | `github`, `gitlab`, `gitea` |
| `cache` | Controls caching behavior for the resolved resource | `always`, `never`, `auto` |

## Requirements

Expand Down Expand Up @@ -55,6 +56,16 @@ for the name, namespace and defaults that the resolver ships with.
| `api-token-secret-namespace` | The namespace containing the token secret, if not `default`. | `other-namespace` |
| `default-org` | The default organization to look for repositories under when using the authenticated API, if not specified in the resolver parameters. Optional. | `tektoncd`, `kubernetes` |

### Caching Options

The git resolver supports caching of resolved resources to improve performance. The caching behavior can be configured using the `cache` option:

| Cache Value | Description |
|-------------|-------------|
| `always` | Always cache resolved resources. This is the most aggressive caching strategy and will cache all resolved resources regardless of their source. |
| `never` | Never cache resolved resources. This disables caching completely. |
| `auto` | Caching will only occur when revision is a commit hash. (default) |

## Usage

The `git` resolver has two modes: cloning a repository with `git clone` (with
Expand Down
12 changes: 12 additions & 0 deletions docs/resolution.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ accompanying [resolver-template](./resolver-template).
For a table of the interfaces and methods a resolver must implement
along with those that are optional, see [resolver-reference.md](./resolver-reference.md).

## Resolver Cache Configuration

The resolver cache is used to improve performance by caching resolved resources for bundle and git resolver. By default, the cache uses:
- 5 minutes ("5m") as the time-to-live (TTL) for cache entries
- 1000 entries as the maximum cache size

You can override these defaults by editing the `resolver-cache-config.yaml` ConfigMap in the `tekton-pipelines-resolvers` namespace. Set the following keys:
- `max-size`: Set the maximum number of cache entries (e.g., "500")
- `default-ttl`: Set the default TTL for cache entries (e.g., "10m", "30s")

If these values are missing or invalid, the defaults will be used.

---

Except as otherwise noted, the content of this page is licensed under the
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
---
# This example demonstrates how TaskRunSpecs can override timeout settings
# defined in the Pipeline spec, providing more granular timeout control
apiVersion: tekton.dev/v1
kind: Task
metadata:
Expand All @@ -21,8 +24,8 @@ spec:
script: |
#!/bin/sh
echo "- Pipeline task timeout: 60s (defined in pipeline spec)"
echo "- TaskRunSpecs override: 20s (defined in pipelinerun spec)"
echo "- Actual task duration: 10s (within 20s override timeout)"
echo "- TaskRunSpecs override: 45s (defined in pipelinerun spec)"
echo "- Actual task duration: 10s (within 45s override timeout)"
---
apiVersion: tekton.dev/v1
kind: Pipeline
Expand All @@ -32,14 +35,15 @@ spec:
tasks:
- name: long-running-task
taskRef:
name: sleep-task
kind: Task
timeout: "60s" # pipeline task timeout (will be overridden to 20s)
name: sleep-task
timeout: 1m0s # 60 seconds - this is the baseline timeout
- name: verify-timeout
runAfter:
- long-running-task
taskRef:
name: verify-task
kind: Task
runAfter: ["long-running-task"]
name: verify-task
---
apiVersion: tekton.dev/v1
kind: PipelineRun
Expand All @@ -50,4 +54,5 @@ spec:
name: taskrun-timeout-override
taskRunSpecs:
- pipelineTaskName: long-running-task
timeout: "20s" # 20s timeout (can't actually test with a timeout lesser than 10s else the task fails)
serviceAccountName: default
timeout: 45s # Override: reduced from 60s to 45s to demonstrate override functionality
9 changes: 9 additions & 0 deletions pkg/apis/config/resolver/feature_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ func NewFeatureFlagsFromMap(cfgMap map[string]string) (*FeatureFlags, error) {
return &tc, nil
}

// AnyResolverEnabled returns true if any resolver is enabled
func (ff *FeatureFlags) AnyResolverEnabled() bool {
return ff.EnableGitResolver ||
ff.EnableHubResolver ||
ff.EnableBundleResolver ||
ff.EnableClusterResolver ||
ff.EnableHttpResolver
}

// NewFeatureFlagsFromConfigMap returns a Config for the given configmap
func NewFeatureFlagsFromConfigMap(config *corev1.ConfigMap) (*FeatureFlags, error) {
return NewFeatureFlagsFromMap(config.Data)
Expand Down
62 changes: 62 additions & 0 deletions pkg/apis/config/resolver/feature_flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,68 @@ func TestNewFeatureFlagsConfigMapErrors(t *testing.T) {
}
}

func TestAnyResolverEnabled(t *testing.T) {
testCases := []struct {
name string
flags *resolver.FeatureFlags
expected bool
}{
{
name: "All resolvers enabled",
flags: &resolver.FeatureFlags{
EnableGitResolver: true,
EnableHubResolver: true,
EnableBundleResolver: true,
EnableClusterResolver: true,
EnableHttpResolver: true,
},
expected: true,
},
{
name: "All resolvers disabled",
flags: &resolver.FeatureFlags{
EnableGitResolver: false,
EnableHubResolver: false,
EnableBundleResolver: false,
EnableClusterResolver: false,
EnableHttpResolver: false,
},
expected: false,
},
{
name: "Only git resolver enabled",
flags: &resolver.FeatureFlags{
EnableGitResolver: true,
EnableHubResolver: false,
EnableBundleResolver: false,
EnableClusterResolver: false,
EnableHttpResolver: false,
},
expected: true,
},
{
name: "Only bundle resolver enabled",
flags: &resolver.FeatureFlags{
EnableGitResolver: false,
EnableHubResolver: false,
EnableBundleResolver: true,
EnableClusterResolver: false,
EnableHttpResolver: false,
},
expected: true,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result := tc.flags.AnyResolverEnabled()
if result != tc.expected {
t.Errorf("AnyResolverEnabled() = %t, want %t", result, tc.expected)
}
})
}
}

func verifyConfigFileWithExpectedFeatureFlagsConfig(t *testing.T, fileName string, expectedConfig *resolver.FeatureFlags) {
t.Helper()
cm := test.ConfigMapFromTestFile(t, fileName)
Expand Down
Loading
Loading