Remove the integrity hash annotation - #4643
Conversation
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The changes are mechanical dead-code removal consistent with the stated migration plan, and the updated tests align with the intended absence of the annotation.
Review tier: Lite
Findings: None
What changed in this PR
This PR removes the write-only actions.github.com/integrity-hash annotation and the helper hashing APIs that previously fed it, completing another layer in the migration to the newer update-detection mechanisms introduced in earlier layers (#4575 context).
Changes:
- Removes integrity-hash annotation stamping and associated helper hash functions from the resource builder.
- Simplifies resource-cache object ref versioning by dropping the integrity-hash fallback branch.
- Removes now-unused
Hash()helper methods from v1alpha1 spec types and updates tests to assert the annotation is absent.
| File | Description |
|---|---|
| controllers/actions.github.com/resourcebuilder.go | Deletes integrity-hash constant, helper hash functions, and all annotation write call sites. |
| controllers/actions.github.com/resourcecache.go | Removes integrity-hash fallback when deriving cache object “resource versions.” |
| apis/actions.github.com/v1alpha1/autoscalinglistener_types.go | Drops AutoscalingListenerSpec.Hash() and unused hash import. |
| apis/actions.github.com/v1alpha1/ephemeralrunner_types.go | Drops EphemeralRunnerSpec.Hash() and unused hash import. |
| controllers/actions.github.com/resourcebuilder_test.go | Updates assertions to ensure the integrity-hash annotation is not present; renames proxy secret test accordingly. |
| controllers/actions.github.com/resourcecache_test.go | Removes integrity-hash annotation setup from test fixtures. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
536975948763
humbertohlgl
El sept 9, 2026, 04:31 -0600, Nikola Jokic ***@***.***>, escribió:
… Layer 6 of a 7-part split of #4575.
What
Mechanical dead-code removal of the actions.github.com/integrity-hash annotation and everything that fed it.
• controllers/actions.github.com/resourcebuilder.go: delete the annotationKeyIntegrityHash constant, the remaining hash helpers (scaleSetListenerConfigIntegrityHash, scaleSetListenerServiceAccountIntegrityHash, scaleSetRoleIntegrityHash, scaleSetListenerRoleBindingIntegrityHash, autoscalingListenerProxySecretIntegrityHash, ephemeralRunnerSetProxySecretZIdentityHash), and every call site that stamped the annotation onto an object. newAutoscalingListener now starts from var annotations map[string]string.
• controllers/actions.github.com/resourcecache.go: drop the integrity-hash fallback branch in newResourceCacheObjectRef.
• apis/actions.github.com/v1alpha1: delete AutoscalingListenerSpec.Hash() and EphemeralRunnerSpec.Hash() plus the now-unused hash imports.
• Tests updated to assert the annotation is absent; TestEphemeralRunnerSetProxySecretZIdentityHash becomes TestEphemeralRunnerSetProxySecretMetadata.
Why this is safe
Layers 2-4 already removed every reader of the integrity hash, so all that remained were write-only dead paths. Nothing in this PR changes reconcile behaviour.
Behavioural implication
Managed objects no longer carry the actions.github.com/integrity-hash annotation. Update detection is now handled entirely by the mechanisms introduced in layers 2-4.
Validation
• go build ./... ✅
• go vet ./... ✅
• go test ./controllers/actions.github.com/... ./apis/... ✅ (envtest suite, 224s)
You can view, comment on, or merge this pull request online at:
#4643
Commit Summary
• f098053 Remove the integrity hash annotation
File Changes
(6 files)
• M apis/actions.github.com/v1alpha1/autoscalinglistener_types.go (5)
• M apis/actions.github.com/v1alpha1/ephemeralrunner_types.go (5)
• M controllers/actions.github.com/resourcebuilder.go (101)
• M controllers/actions.github.com/resourcebuilder_test.go (19)
• M controllers/actions.github.com/resourcecache.go (3)
• M controllers/actions.github.com/resourcecache_test.go (15)
Patch Links:
• https://github.com/actions/actions-runner-controller/pull/4643.patch
• https://github.com/actions/actions-runner-controller/pull/4643.diff
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
19dc280 to
a3569dc
Compare
a3569dc to
bcb101e
Compare
bcb101e to
58c7973
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Legacy annotations are not cleaned up, and existing listeners may be unnecessarily recreated during upgrade.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review tier: Lite
Findings: 1
New issues introduced by this change (2)
| Severity | Finding |
|---|---|
controllers/actions.github.com/resourcebuilder.go — Existing AutoscalingListener objects still carry the annotation written by the previous builder.… |
|
controllers/actions.github.com/resourcebuilder.go — This only removes the key from newly built desired objects; it does not remove the legacy… |
Suppressed comments (1)
controllers/actions.github.com/resourcebuilder_test.go:231
- This assertion only covers a newly constructed Secret. Secrets created before this change still contain the old integrity annotation, and the EphemeralRunnerSet reconciler merges live annotations into the desired set before patching (ephemeralrunnerset_controller.go:644-655), so the old key is preserved indefinitely and managed proxy Secrets do not actually lose it after upgrade. Add legacy-key cleanup to reconciliation or narrow the stated removal behavior, with an existing-Secret test.
assert.NotContains(t, proxySecret.Annotations, "actions.github.com/integrity-hash")
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Resolve the exported API compatibility breaks and the empty-annotations reconciliation loop.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review tier: Lite
Findings: 2
New issues introduced by this change (2)
| Severity | Finding |
|---|---|
apis/actions.github.com/v1alpha1/autoscalinglistener_types.go — Removing AutoscalingListenerSpec.Hash() is source-incompatible for downstream Go consumers of… |
|
apis/actions.github.com/v1alpha1/ephemeralrunner_types.go — Removing EphemeralRunnerSpec.Hash() is source-incompatible for downstream Go consumers of this… |
Issues resolved since last review (2)
| Severity | Finding |
|---|---|
controllers/actions.github.com/resourcebuilder.go — This only removes the key from newly built desired objects; it does not remove the legacy… View resolved comment |
|
controllers/actions.github.com/resourcebuilder.go — Existing AutoscalingListener objects still carry the annotation written by the previous builder.… View resolved comment |
Suppressed comments (1)
controllers/actions.github.com/resourcebuilder.go:183
- When
AutoscalingListenerMetadata.Annotationsis an explicitly empty map,mergeAnnotationsreturns a non-nil empty map. The desired listener is compared withcmp.Equalagainst the live annotations, butmetadata.annotationsis omitted when this object is serialized, so the created listener is read back with a nil map; nil and empty maps compare unequal and the reconciler will delete/recreate it on every pass. Normalize emptyannotationsto nil before assigning it to the listener (and add a regression test for empty metadata).
var annotations map[string]string
if autoscalingRunnerSet.Spec.AutoscalingListenerMetadata != nil {
labels = b.filterAndMergeLabels(autoscalingRunnerSet.Spec.AutoscalingListenerMetadata.Labels, labels)
annotations = b.mergeAnnotations(autoscalingRunnerSet.Spec.AutoscalingListenerMetadata.Annotations, annotations)
| @@ -87,10 +86,6 @@ type AutoscalingListenerSpec struct { | |||
| ListenerConfig *ListenerConfig `json:"listenerConfig,omitempty"` | |||
| } | |||
|
|
|||
| @@ -133,10 +132,6 @@ type EphemeralRunnerSpec struct { | |||
| corev1.PodTemplateSpec `json:",inline"` | |||
| } | |||
|
|
|||
5905d48 to
e3246d7
Compare
e3246d7 to
752765e
Compare
Layers 2-4 removed every reader of the actions.github.com/integrity-hash annotation, so what remained were write-only dead paths. Delete the annotation constant, all remaining hash helpers that computed it, the call sites that stamped it onto objects, the integrity-hash fallback in newResourceCacheObjectRef, and the now-unused AutoscalingListenerSpec.Hash and EphemeralRunnerSpec.Hash methods. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Code review raised two upgrade consequences of no longer stamping actions.github.com/integrity-hash. Both are real, and neither is covered by a test, so cover them. The AutoscalingRunnerSet reconciler compares a live listener's annotations against the desired ones exactly, so a listener created by an older controller is replaced on the first reconcile after an upgrade. That rollout is one-time rather than a loop, because the replacement is built by the same path and carries no annotation. It is not additional either: the listener runs the manager's own image, so a controller upgrade already forces the same recreation through the Spec comparison. Reconcilers that update objects in place merge live annotations under the desired ones, so the annotation survives on objects that already carry it. Nothing reads it any more, so it is inert metadata; stripping it would mean patching every managed object on upgrade, which is a separate decision. Both tests were mutation-checked: re-stamping the annotation fails the first, and stripping the key in mergeAnnotations fails the second. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
6b6011c to
099703a
Compare


Layer 6 of a 7-part split of #4575.
What
Mechanical dead-code removal of the
actions.github.com/integrity-hashannotation and everything that fed it.controllers/actions.github.com/resourcebuilder.go: delete theannotationKeyIntegrityHashconstant, the remaining hash helpers (scaleSetListenerConfigIntegrityHash,scaleSetListenerServiceAccountIntegrityHash,scaleSetRoleIntegrityHash,scaleSetListenerRoleBindingIntegrityHash,autoscalingListenerProxySecretIntegrityHash,ephemeralRunnerSetProxySecretZIdentityHash), and every call site that stamps the annotation onto an object.newAutoscalingListenernow starts fromvar annotations map[string]string.controllers/actions.github.com/resourcecache.go: drop the integrity-hash fallback branch innewResourceCacheObjectRef.apis/actions.github.com/v1alpha1: deleteAutoscalingListenerSpec.Hash()andEphemeralRunnerSpec.Hash()plus the now-unusedhashimports.TestEphemeralRunnerSetProxySecretZIdentityHashbecomesTestEphemeralRunnerSetProxySecretMetadata.Why this is safe
Layers 2-4 already removed every reader of the integrity hash, so all that remained were write-only dead paths. Nothing in this PR changes reconcile behaviour.
Behavioural implication
Newly built objects no longer carry
actions.github.com/integrity-hash. Update detection is handled entirely by the mechanisms introduced in layers 2-4.Two upgrade consequences are worth stating precisely, both now covered by tests in
resourcebuilder_legacy_annotation_test.go:Existing listeners are recreated once.
AutoscalingRunnerSetReconcilercompares the live listener's annotations against the desired ones withcmp.Equal, so a listener created by an older controller — which carries the annotation — no longer matches and is deleted and rebuilt on the first reconcile after upgrade. This is a one-time rollout, not a loop: the replacement comes from the same code path and carries no annotation, so the next comparison matches. It is also not additional churn in practice, because the listener runs the manager's own image (CONTROLLER_MANAGER_CONTAINER_IMAGE), so any controller version upgrade already changesSpec.Imageand forces the same recreation.The annotation is not migrated off objects that already have it. Reconcilers that update an object in place merge live annotations under the desired ones (
mergeAnnotations(live, desired)), so a key that is merely absent from the desired set survives. Pre-existing EphemeralRunnerSets, service accounts, roles, role bindings and proxy/config Secrets therefore keep the annotation. Since layers 2-4 removed every reader, it is inert metadata rather than a behavioural leftover. Actively stripping it would mean patching every managed object across every scale set on upgrade — a deliberate migration, and a separate decision from this removal.Validation
go build ./...,go vet ./...,gofmt -l apis/ controllers/— cleanmake manifestsleavesgit status --porcelainempty (CRDs in sync)go test ./controllers/actions.github.com/... ./apis/...—ok(envtest, 238s)mergeAnnotationsfails the second.