From 71ced6515965fdfea00ece44e6e83939d544bab2 Mon Sep 17 00:00:00 2001 From: Nikola Jokic Date: Wed, 9 Sep 2026 12:30:57 +0200 Subject: [PATCH] Remove the integrity hash annotation 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> --- .../v1alpha1/autoscalinglistener_types.go | 5 - .../v1alpha1/ephemeralrunner_types.go | 5 - .../actions.github.com/resourcebuilder.go | 101 +----------------- .../resourcebuilder_test.go | 19 ++-- .../actions.github.com/resourcecache.go | 3 - .../actions.github.com/resourcecache_test.go | 15 --- 6 files changed, 9 insertions(+), 139 deletions(-) diff --git a/apis/actions.github.com/v1alpha1/autoscalinglistener_types.go b/apis/actions.github.com/v1alpha1/autoscalinglistener_types.go index b1bb0136..3c4b3b3a 100644 --- a/apis/actions.github.com/v1alpha1/autoscalinglistener_types.go +++ b/apis/actions.github.com/v1alpha1/autoscalinglistener_types.go @@ -17,7 +17,6 @@ limitations under the License. package v1alpha1 import ( - "github.com/actions/actions-runner-controller/hash" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -87,10 +86,6 @@ type AutoscalingListenerSpec struct { ListenerConfig *ListenerConfig `json:"listenerConfig,omitempty"` } -func (s *AutoscalingListenerSpec) Hash() string { - return hash.ComputeTemplateHash(s) -} - // AutoscalingListenerStatus defines the observed state of AutoscalingListener type AutoscalingListenerStatus struct{} diff --git a/apis/actions.github.com/v1alpha1/ephemeralrunner_types.go b/apis/actions.github.com/v1alpha1/ephemeralrunner_types.go index c97b5595..4c4a2ace 100644 --- a/apis/actions.github.com/v1alpha1/ephemeralrunner_types.go +++ b/apis/actions.github.com/v1alpha1/ephemeralrunner_types.go @@ -17,7 +17,6 @@ limitations under the License. package v1alpha1 import ( - "github.com/actions/actions-runner-controller/hash" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -133,10 +132,6 @@ type EphemeralRunnerSpec struct { corev1.PodTemplateSpec `json:",inline"` } -func (s *EphemeralRunnerSpec) Hash() string { - return hash.ComputeTemplateHash(s) -} - // EphemeralRunnerStatus defines the observed state of EphemeralRunner type EphemeralRunnerStatus struct { // Turns true only if the runner is online. diff --git a/controllers/actions.github.com/resourcebuilder.go b/controllers/actions.github.com/resourcebuilder.go index e5349670..7cbcd9aa 100644 --- a/controllers/actions.github.com/resourcebuilder.go +++ b/controllers/actions.github.com/resourcebuilder.go @@ -46,15 +46,6 @@ var commonLabelKeys = [...]string{ LabelKeyGitHubRepository, } -// annotationKeyIntegrityHash is used as a hash of the important fields -// of each resource to determine if more drastic action should be taken. -// -// For example, annotations/labels are not something that should modify -// the behavior of a resource, while the change in spec is. Therefore, -// the spec hash should contain the spec fields in order to determine -// modifications. -const annotationKeyIntegrityHash = "actions.github.com/integrity-hash" - const labelValueKubernetesPartOf = "gha-runner-scale-set" var ( @@ -185,9 +176,7 @@ func (b *ResourceBuilder) newAutoscalingListener(autoscalingRunnerSet *v1alpha1. return nil, fmt.Errorf("failed to apply GitHub URL labels: %v", err) } - annotations := map[string]string{ - annotationKeyIntegrityHash: spec.Hash(), - } + var annotations map[string]string if autoscalingRunnerSet.Spec.AutoscalingListenerMetadata != nil { labels = b.filterAndMergeLabels(autoscalingRunnerSet.Spec.AutoscalingListenerMetadata.Labels, labels) @@ -322,8 +311,6 @@ func (b *ResourceBuilder) newScaleSetListenerConfig(autoscalingListener *v1alpha }, } - desiredSecret.Annotations[annotationKeyIntegrityHash] = scaleSetListenerConfigIntegrityHash(desiredSecret) - if err := b.setControllerReference(autoscalingListener, desiredSecret); err != nil { return nil, fmt.Errorf("failed to set controller reference for listener config secret: %w", err) } @@ -331,18 +318,6 @@ func (b *ResourceBuilder) newScaleSetListenerConfig(autoscalingListener *v1alpha return desiredSecret, nil } -func scaleSetListenerConfigIntegrityHash(secret *corev1.Secret) string { - type data struct { - Data map[string][]byte `json:"data,omitempty"` - } - - d := data{ - Data: secret.Data, - } - - return hash.ComputeTemplateHash(&d) -} - func (b *ResourceBuilder) newScaleSetListenerPod( autoscalingListener *v1alpha1.AutoscalingListener, podConfig *corev1.Secret, @@ -643,8 +618,6 @@ func (b *ResourceBuilder) newScaleSetListenerServiceAccount(autoscalingListener base.Annotations = b.mergeAnnotations(autoscalingListener.Spec.ServiceAccountMetadata.Annotations, base.Annotations) } - base.Annotations[annotationKeyIntegrityHash] = scaleSetListenerServiceAccountIntegrityHash(base) - if err := b.setControllerReference(autoscalingListener, base); err != nil { return nil, fmt.Errorf("failed to set controller reference for listener service account: %w", err) } @@ -653,22 +626,6 @@ func (b *ResourceBuilder) newScaleSetListenerServiceAccount(autoscalingListener return base, nil } -func scaleSetListenerServiceAccountIntegrityHash(sa *corev1.ServiceAccount) string { - type data struct { - Secrets []corev1.ObjectReference `json:"secrets"` - ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets"` - AutomountServiceAccountToken *bool `json:"automountServiceAccountToken"` - } - - d := data{ - Secrets: sa.Secrets, - ImagePullSecrets: sa.ImagePullSecrets, - AutomountServiceAccountToken: sa.AutomountServiceAccountToken, - } - - return hash.ComputeTemplateHash(&d) -} - func (b *ResourceBuilder) newScaleSetListenerRole(autoscalingListener *v1alpha1.AutoscalingListener) *rbacv1.Role { cacheKeyObject := &rbacv1.Role{ ObjectMeta: metav1.ObjectMeta{ @@ -707,24 +664,11 @@ func (b *ResourceBuilder) newScaleSetListenerRole(autoscalingListener *v1alpha1. Rules: rulesForListenerRole([]string{autoscalingListener.Spec.EphemeralRunnerSetName}), } - newRole.Annotations[annotationKeyIntegrityHash] = scaleSetRoleIntegrityHash(newRole) b.ResourceCache.listenerRole.Upsert(autoscalingListener, newRole) return newRole } -func scaleSetRoleIntegrityHash(role *rbacv1.Role) string { - type data struct { - Rules []rbacv1.PolicyRule `json:"rules"` - } - - d := data{ - Rules: role.Rules, - } - - return hash.ComputeTemplateHash(&d) -} - func (b *ResourceBuilder) newScaleSetListenerRoleBinding(autoscalingListener *v1alpha1.AutoscalingListener, listenerRole *rbacv1.Role, serviceAccount *corev1.ServiceAccount) *rbacv1.RoleBinding { cacheKeyObject := &rbacv1.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ @@ -777,26 +721,11 @@ func (b *ResourceBuilder) newScaleSetListenerRoleBinding(autoscalingListener *v1 Subjects: subjects, } - newRoleBinding.Annotations[annotationKeyIntegrityHash] = scaleSetListenerRoleBindingIntegrityHash(newRoleBinding) b.ResourceCache.listenerRoleBinding.Upsert(autoscalingListener, newRoleBinding, listenerRole, serviceAccount) return newRoleBinding } -func scaleSetListenerRoleBindingIntegrityHash(rb *rbacv1.RoleBinding) string { - type data struct { - RoleRef rbacv1.RoleRef `json:"roleRef"` - Subjects []rbacv1.Subject `json:"subjects"` - } - - d := data{ - RoleRef: rb.RoleRef, - Subjects: rb.Subjects, - } - - return hash.ComputeTemplateHash(&d) -} - func (b *ResourceBuilder) newEphemeralRunnerSet(autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet) (*v1alpha1.EphemeralRunnerSet, error) { runnerScaleSetID, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIDAnnotationKey]) if err != nil { @@ -886,8 +815,6 @@ func (b *ResourceBuilder) newAutoscalingListenerProxySecret(autoscalingListener Data: data, } - newProxySecret.Annotations[annotationKeyIntegrityHash] = autoscalingListenerProxySecretIntegrityHash(newProxySecret) - if err := b.setControllerReference(autoscalingListener, newProxySecret); err != nil { return nil, fmt.Errorf("failed to set controller reference for listener proxy secret: %w", err) } @@ -895,18 +822,6 @@ func (b *ResourceBuilder) newAutoscalingListenerProxySecret(autoscalingListener return newProxySecret, nil } -func autoscalingListenerProxySecretIntegrityHash(secret *corev1.Secret) string { - type data struct { - Data map[string][]byte `json:"data"` - } - - d := data{ - Data: secret.Data, - } - - return hash.ComputeTemplateHash(&d) -} - func (b *ResourceBuilder) newEphemeralRunner(ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet) (*v1alpha1.EphemeralRunner, error) { labels := make(map[string]string, len(ephemeralRunnerSet.Labels)) maps.Copy(labels, ephemeralRunnerSet.Labels) @@ -1053,8 +968,6 @@ func (b *ResourceBuilder) newEphemeralRunnerSetProxySecret(ephemeralRunnerSet *v Data: data, } - runnerPodProxySecret.Annotations[annotationKeyIntegrityHash] = ephemeralRunnerSetProxySecretZIdentityHash(runnerPodProxySecret) - if err := b.setControllerReference(ephemeralRunnerSet, runnerPodProxySecret); err != nil { return nil, fmt.Errorf("failed to set controller reference for ephemeral runner set proxy secret: %w", err) } @@ -1062,18 +975,6 @@ func (b *ResourceBuilder) newEphemeralRunnerSetProxySecret(ephemeralRunnerSet *v return runnerPodProxySecret, nil } -func ephemeralRunnerSetProxySecretZIdentityHash(secret *corev1.Secret) string { - type data struct { - Data map[string][]byte `json:"data"` - } - - d := data{ - Data: secret.Data, - } - - return hash.ComputeTemplateHash(&d) -} - func scaleSetListenerConfigName(autoscalingListener *v1alpha1.AutoscalingListener) string { return autoscalingListener.Name + "-config" } diff --git a/controllers/actions.github.com/resourcebuilder_test.go b/controllers/actions.github.com/resourcebuilder_test.go index e865dd81..9e91790d 100644 --- a/controllers/actions.github.com/resourcebuilder_test.go +++ b/controllers/actions.github.com/resourcebuilder_test.go @@ -115,7 +115,7 @@ func TestMetadataPropagation(t *testing.T) { assert.Equal(t, labelValueKubernetesPartOf, ephemeralRunnerSet.Labels[LabelKeyKubernetesPartOf]) assert.Equal(t, "runner-set", ephemeralRunnerSet.Labels[LabelKeyKubernetesComponent]) assert.Equal(t, autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion], ephemeralRunnerSet.Labels[LabelKeyKubernetesVersion]) - assert.NotContains(t, ephemeralRunnerSet.Annotations, annotationKeyIntegrityHash) + assert.NotContains(t, ephemeralRunnerSet.Annotations, "actions.github.com/integrity-hash") assert.Equal(t, autoscalingRunnerSet.Name, ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetName]) assert.Equal(t, autoscalingRunnerSet.Namespace, ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetNamespace]) assert.Equal(t, "", ephemeralRunnerSet.Labels[LabelKeyGitHubEnterprise]) @@ -132,7 +132,7 @@ func TestMetadataPropagation(t *testing.T) { assert.Equal(t, labelValueKubernetesPartOf, listener.Labels[LabelKeyKubernetesPartOf]) assert.Equal(t, "runner-scale-set-listener", listener.Labels[LabelKeyKubernetesComponent]) assert.Equal(t, autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion], listener.Labels[LabelKeyKubernetesVersion]) - assert.NotEmpty(t, listener.Annotations[annotationKeyIntegrityHash]) + assert.NotContains(t, listener.Annotations, "actions.github.com/integrity-hash") assert.Equal(t, autoscalingRunnerSet.Name, listener.Labels[LabelKeyGitHubScaleSetName]) assert.Equal(t, autoscalingRunnerSet.Namespace, listener.Labels[LabelKeyGitHubScaleSetNamespace]) assert.Equal(t, "", listener.Labels[LabelKeyGitHubEnterprise]) @@ -206,7 +206,7 @@ func TestMetadataPropagation(t *testing.T) { } } -func TestEphemeralRunnerSetProxySecretZIdentityHash(t *testing.T) { +func TestEphemeralRunnerSetProxySecretMetadata(t *testing.T) { ephemeralRunnerSet := &v1alpha1.EphemeralRunnerSet{ ObjectMeta: metav1.ObjectMeta{ Name: "test-scale-set", @@ -224,13 +224,11 @@ func TestEphemeralRunnerSetProxySecretZIdentityHash(t *testing.T) { }) require.NoError(t, err) - actualHash := proxySecret.Annotations[annotationKeyIntegrityHash] - assert.NotEmpty(t, actualHash) - assert.Equal(t, ephemeralRunnerSetProxySecretZIdentityHash(proxySecret), actualHash) - - changedProxySecret := proxySecret.DeepCopy() - changedProxySecret.Data["http_proxy"] = []byte("http://updated-proxy.example.com") - assert.NotEqual(t, actualHash, ephemeralRunnerSetProxySecretZIdentityHash(changedProxySecret)) + assert.Equal(t, proxyEphemeralRunnerSetSecretName(ephemeralRunnerSet), proxySecret.Name) + assert.Equal(t, ephemeralRunnerSet.Namespace, proxySecret.Namespace) + assert.Equal(t, ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetName], proxySecret.Labels[LabelKeyGitHubScaleSetName]) + assert.Equal(t, ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetNamespace], proxySecret.Labels[LabelKeyGitHubScaleSetNamespace]) + assert.NotContains(t, proxySecret.Annotations, "actions.github.com/integrity-hash") } func TestGitHubURLTrimLabelValues(t *testing.T) { @@ -318,7 +316,6 @@ func TestOwnershipRelationships(t *testing.T) { runnerScaleSetIDAnnotationKey: "1", AnnotationKeyGitHubRunnerGroupName: "test-group", AnnotationKeyGitHubRunnerScaleSetName: "test-scale-set", - annotationKeyIntegrityHash: "test-hash", }, }, Spec: v1alpha1.AutoscalingRunnerSetSpec{ diff --git a/controllers/actions.github.com/resourcecache.go b/controllers/actions.github.com/resourcecache.go index 2a4b1c10..d6122914 100644 --- a/controllers/actions.github.com/resourcecache.go +++ b/controllers/actions.github.com/resourcecache.go @@ -246,9 +246,6 @@ func (k resourceCacheDependencyKey) Equal(other resourceCacheDependencyKey) bool func newResourceCacheObjectRef(object client.Object) ResourceCacheObjectRef { resourceVersion := object.GetResourceVersion() - if resourceVersion == "" { - resourceVersion = object.GetAnnotations()[annotationKeyIntegrityHash] - } if resourceVersion == "" { resourceVersion = hash.ComputeTemplateHash(object) } diff --git a/controllers/actions.github.com/resourcecache_test.go b/controllers/actions.github.com/resourcecache_test.go index 608ed9d9..e187ac5e 100644 --- a/controllers/actions.github.com/resourcecache_test.go +++ b/controllers/actions.github.com/resourcecache_test.go @@ -187,9 +187,6 @@ func TestResourceBuilderCachesListenerPodDependencies(t *testing.T) { Name: "listener", Namespace: "controller-ns", UID: "listener-uid", - Annotations: map[string]string{ - annotationKeyIntegrityHash: "listener-hash", - }, }, Spec: v1alpha1.AutoscalingListenerSpec{ Image: "listener:latest", @@ -204,9 +201,6 @@ func TestResourceBuilderCachesListenerPodDependencies(t *testing.T) { Namespace: "controller-ns", UID: "config-secret-uid", ResourceVersion: "11", - Annotations: map[string]string{ - annotationKeyIntegrityHash: "config-hash", - }, }, } serviceAccount := &corev1.ServiceAccount{ @@ -215,9 +209,6 @@ func TestResourceBuilderCachesListenerPodDependencies(t *testing.T) { Namespace: "controller-ns", UID: "service-account-uid", ResourceVersion: "12", - Annotations: map[string]string{ - annotationKeyIntegrityHash: "service-account-hash", - }, }, } role := &rbacv1.Role{ @@ -226,9 +217,6 @@ func TestResourceBuilderCachesListenerPodDependencies(t *testing.T) { Namespace: "scale-set-ns", UID: "role-uid", ResourceVersion: "13", - Annotations: map[string]string{ - annotationKeyIntegrityHash: "role-hash", - }, }, } roleBinding := &rbacv1.RoleBinding{ @@ -237,9 +225,6 @@ func TestResourceBuilderCachesListenerPodDependencies(t *testing.T) { Namespace: "scale-set-ns", UID: "role-binding-uid", ResourceVersion: "14", - Annotations: map[string]string{ - annotationKeyIntegrityHash: "role-binding-hash", - }, }, }