Skip to content

[FEAT repo-guard] - Add listType markers to GithubOrganization team-list fields for SSA merge safety #249

Description

@onuryilmaz

Description

GithubOrganization spec has four list fields that Permission Manager writes via Server-Side Apply (cloudoperators/permission-manager#67):

  • spec.defaultPublicRepositoryTeams ([]GithubTeamWithPermission)
  • spec.defaultPrivateRepositoryTeams ([]GithubTeamWithPermission)
  • spec.defaultInternalRepositoryTeams ([]GithubTeamWithPermission)
  • spec.organizationOwnerTeams ([]string)

These are currently untagged, so Kubernetes treats them as listType=atomic — the entire list is a single owned value. With max-concurrent-reconciles=5, two ASR reconciles on the same org both do SSA applies with the same field manager (permission-manager). Because the lists are atomic, the second apply clobbers the first ASR's entries.

Fix: Add kubebuilder list-type markers so the apiserver merges by element key instead of replacing the whole list atomically.

Changes

api/v1/githuborganization_types.go

// +listType=map
// +listMapKey=team
DefaultPublicRepositoryTeams   []GithubTeamWithPermission

// +listType=map
// +listMapKey=team
DefaultPrivateRepositoryTeams  []GithubTeamWithPermission

// +listType=map
// +listMapKey=team
DefaultInternalRepositoryTeams []GithubTeamWithPermission

// +listType=set
OrganizationOwnerTeams         []string

GithubTeamWithPermission.team is the natural unique key. OrganizationOwnerTeams is []string so it becomes a set.

Then run make manifests — this adds x-kubernetes-list-type: map / x-kubernetes-list-map-keys: [team] to the three struct-list fields and x-kubernetes-list-type: set to organizationOwnerTeams in:

  • config/crd/bases/repo-guard.cloudoperators.dev_githuborganizations.yaml
  • charts/repo-guard/crds/githuborganization-crd.yaml

No controller logic changes needed — listType is a pure apiserver/SSA instruction.

Result

Two PM reconciles applying different team entries concurrently produce the correct merged result — no silent overwrites. This unblocks cloudoperators/permission-manager#67 from safely removing RetryOnConflict without introducing the race described in cloudoperators/permission-manager#66.

Reference Issues

Part of epic: cloudoperators/permission-manager#66 — GithubOrganization: Ownership, Concurrency, and Missing Fields
Unblocks: cloudoperators/permission-manager#67 — Implement GithubOrganization writes via Server-Side Apply

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    backlogReady for sprint planning; triggers project additionfeatureNew functionality or enhancementneeds-refinementNeeds scoping before implementation

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions