Skip to content

fix: use csapgrade to patch managedFields for client-side apply migration#26289

Merged
reggie-k merged 9 commits intoargoproj:masterfrom
pjiang-dev:pjiang/fix-csa-migration
Feb 19, 2026
Merged

fix: use csapgrade to patch managedFields for client-side apply migration#26289
reggie-k merged 9 commits intoargoproj:masterfrom
pjiang-dev:pjiang/fix-csa-migration

Conversation

@pjiang-dev
Copy link
Copy Markdown
Contributor

@pjiang-dev pjiang-dev commented Feb 5, 2026

fixes #26279
This PR refactors the existing Client Side Migration feature https://argo-cd.readthedocs.io/en/latest/user-guide/sync-options/#client-side-apply-migration to use the https://pkg.go.dev/k8s.io/client-go/util/csaupgrade to patch managedFields instead of using a client-side-apply as we were hitting issues with CRDs getting Too long: may not be more than 262144 bytes

Checklist:

  • Either (a) I've created an enhancement proposal and discussed it with the community, (b) this is a bug fix, or (c) this does not need to be in the release notes.
  • The title of the PR states what changed and the related issues number (used for the release note).
  • The title of the PR conforms to the Title of the PR
  • I've included "Closes [ISSUE #]" or "Fixes [ISSUE #]" in the description to automatically close the associated issue.
  • I've updated both the CLI and UI to expose my feature, or I plan to submit a second PR with them.
  • Does this PR require documentation updates?
  • I've updated documentation as required by this PR.
  • I have signed off all my commits as required by DCO
  • I have written unit and/or e2e tests for my change. PRs without these are unlikely to be merged.
  • My build is green (troubleshooting builds).
  • My new feature complies with the feature status guidelines.
  • I have added a brief description of why this PR is necessary and/or what this PR solves.
  • Optional. My organization is added to USERS.md.
  • Optional. For bug fixes, I've indicated what older releases this fix should be cherry-picked into (this may or may not happen depending on risk/complexity).

@bunnyshell
Copy link
Copy Markdown

bunnyshell bot commented Feb 5, 2026

❌ Preview Environment deleted from Bunnyshell

Available commands (reply to this comment):

  • 🚀 /bns:deploy to deploy the environment

Copy link
Copy Markdown
Member

@reggie-k reggie-k left a comment

Choose a reason for hiding this comment

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

Thanks for the PR, Peter!

First of all, I apologize for accidentally pushing to your branch the changed manifests I made while testing :(

Next, I am concerned about the text parsing of the annotation size error, and like Alex and Eugene am wondering what would be the downsides of skipping the attempt to perform the CSA migration that uses the annotation in favor of the CSA upgrade?

Also, I have tested the change locally with Argo CD self-managing Kustomize-based bootstrapped Argo CD and it worked - I saw that after the upgrade with SSA, the kubectl-client-side-apply field manager was migrated to argocd-controller, the app was synced and self-upgraded.

The k3s field manager for the AppSet status remained k3s which I think is expected? Unless the status manager should also be argocd-controller.

@pjiang-dev pjiang-dev force-pushed the pjiang/fix-csa-migration branch from c258244 to 5e69366 Compare February 9, 2026 02:28
@pjiang-dev
Copy link
Copy Markdown
Contributor Author

pjiang-dev commented Feb 9, 2026

Thanks for the PR, Peter!

First of all, I apologize for accidentally pushing to your branch the changed manifests I made while testing :(

Next, I am concerned about the text parsing of the annotation size error, and like Alex and Eugene am wondering what would be the downsides of skipping the attempt to perform the CSA migration that uses the annotation in favor of the CSA upgrade?

Also, I have tested the change locally with Argo CD self-managing Kustomize-based bootstrapped Argo CD and it worked - I saw that after the upgrade with SSA, the kubectl-client-side-apply field manager was migrated to argocd-controller, the app was synced and self-upgraded.

The k3s field manager for the AppSet status remained k3s which I think is expected? Unless the status manager should also be argocd-controller.

@reggie-k No worries. After looking more, The original method actually uses the same csaupgrade package so i think its safe to always use this new CSA upgrade.
Its expected to still see k3s for status field or if using regular k8s you would see 'kube-api-server' and this is handled separately from SSA/CSA and should not change

@pjiang-dev pjiang-dev marked this pull request as ready for review February 9, 2026 02:37
@pjiang-dev pjiang-dev requested a review from a team as a code owner February 9, 2026 02:37
@pjiang-dev pjiang-dev force-pushed the pjiang/fix-csa-migration branch from b8ba1fa to 1a4b165 Compare February 9, 2026 17:36
@pjiang-dev pjiang-dev requested a review from a team as a code owner February 9, 2026 18:57
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
@pjiang-dev pjiang-dev force-pushed the pjiang/fix-csa-migration branch from 8bb8975 to cd569c1 Compare February 9, 2026 19:53
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
@rumstead
Copy link
Copy Markdown
Member

@rumstead rumstead requested review from https://github.com/apps/copilot-pull-request-reviewer and removed request for alexrecuenco-hf

I only meant to request copilot, sorry about that!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors Argo CD’s client-side-apply → server-side-apply migration to avoid last-applied-configuration annotation size limits by patching managedFields via k8s.io/client-go/util/csaupgrade, addressing failures on large resources (e.g., CRDs).

Changes:

  • Replace the existing CSA migration step with a csaupgrade-generated JSON patch that updates managedFields.
  • Add unit tests covering the new migration helper behavior.
  • Update user documentation to reflect the new managedFields-based migration flow.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
gitops-engine/pkg/sync/sync_context.go Introduces performCSAUpgradeMigration using csaupgrade and wires it into the SSA apply flow.
gitops-engine/pkg/sync/sync_context_test.go Adds tests validating migration behavior with/without a CSA manager present.
docs/user-guide/sync-options.md Updates migration documentation to describe managedFields patching instead of last-applied annotation usage.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
@pjiang-dev pjiang-dev changed the title fix: use csupgrade to patch managedFields in case annotation is too large fix: use csapgrade to patch managedFields for clientSideApplyMigration Feb 10, 2026
@pjiang-dev pjiang-dev changed the title fix: use csapgrade to patch managedFields for clientSideApplyMigration fix: use csapgrade to patch managedFields for client-side apply migration Feb 10, 2026
@pjiang-dev pjiang-dev requested a review from rumstead February 11, 2026 18:29
err = sc.performClientSideApplyMigration(t.targetObj, sc.clientSideApplyMigrationManager)
err = sc.performCSAUpgradeMigration(t.liveObj, sc.clientSideApplyMigrationManager)
if err != nil {
return common.ResultCodeSyncFailed, fmt.Sprintf("Failed to perform client-side apply migration: %v", err)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i know not your code but should add the resource name here?

fmt.Sprintf("Failed to perform client-side apply migration for %s: %v", kubeutil.GetResourceKey(t.liveObj), err)

@rumstead
Copy link
Copy Markdown
Member

Codewise, it LGTM. Are there any other validations we need to perform to feel comfortable with the changes?

Copy link
Copy Markdown

@alexrecuenco-hf alexrecuenco-hf left a comment

Choose a reason for hiding this comment

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

Sorry for taking so long.

Everything looks good! Except for this race condition.

Does anyone know how we could test this race-condition?

Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
@pjiang-dev
Copy link
Copy Markdown
Contributor Author

pjiang-dev commented Feb 13, 2026

Addressed remaining comments.
I think we'll need to test these scenarios at least manually. I think some of these have been tested already

  1. Self-managed ArgoCD upgrade (kubectl bootstrap → 3.3 SSA - Migration triggered - VERIFIED
  2. Self-managed ArgoCD upgrade (Helm bootstrap → 3.3 SSA) - Migration should not be triggered because helm manager - VERIFIED
  3. Self-managed ArgoCD upgrade (Kustomize bootstrap → 3.3 SSA) - Migration triggered - VERIFIED
  4. ArgoCD managing ArgoCD via ApplicationSet - No cascading failures where a migration error on the ApplicationSet blocks child Applications - VERIFIED
  5. ClientSideApplyMigration=false still works - VERIFIED
  6. Use CSA with "test" manager, use argocd.argoproj.io/client-side-apply-migration-manager: "test" works properly VERIFIED

cc @reggie-k

@codecov
Copy link
Copy Markdown

codecov bot commented Feb 13, 2026

Codecov Report

❌ Patch coverage is 75.67568% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 62.67%. Comparing base (b0488f5) to head (2fbd162).
⚠️ Report is 70 commits behind head on master.

Files with missing lines Patch % Lines
gitops-engine/pkg/sync/sync_context.go 75.67% 6 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #26289      +/-   ##
==========================================
+ Coverage   62.64%   62.67%   +0.03%     
==========================================
  Files         412      412              
  Lines       55467    55585     +118     
==========================================
+ Hits        34746    34840      +94     
- Misses      17396    17416      +20     
- Partials     3325     3329       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@reggie-k
Copy link
Copy Markdown
Member

reggie-k commented Feb 19, 2026

@pjiang-dev So 2 (self managing Helm) is tricky:
Self-managed ArgoCD upgrade (Helm bootstrap → 3.3 SSA) - Migration should not be triggered because helm manager
Actually, when we install Argo CD manually with Helm, no last-applied because Helm does not use it - expected.
But when we self-manage this installation, Argo CD does not use helm install - it uses client side apply. So after self managing, we have last-applied. Now we upgrade to use the image built from your fix (without SSA). This results in an error -> expected. Now we set SSA and it works -> expected (migration was performed).
But after the upgrade + SSA + migration this is how the field managers look like:

- apiVersion: apiextensions.k8s.io/v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          f:helm.sh/resource-policy: {}
        f:labels:
          f:app.kubernetes.io/name: {}
          f:app.kubernetes.io/part-of: {}
      f:spec:
        f:group: {}
        f:names:
          f:kind: {}
          f:listKind: {}
          f:plural: {}
          f:shortNames: {}
          f:singular: {}
        f:scope: {}
        f:versions: {}
    manager: argocd-controller
    operation: Apply
    time: "2026-02-19T03:54:36Z"
  - apiVersion: apiextensions.k8s.io/v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .: {}
          f:helm.sh/resource-policy: {}
          f:meta.helm.sh/release-name: {}
          f:meta.helm.sh/release-namespace: {}
        f:labels:
          .: {}
          f:app.kubernetes.io/managed-by: {}
          f:app.kubernetes.io/name: {}
          f:app.kubernetes.io/part-of: {}
      f:spec:
        f:conversion:
          .: {}
          f:strategy: {}
        f:group: {}
        f:names:
          f:kind: {}
          f:listKind: {}
          f:plural: {}
          f:shortNames: {}
          f:singular: {}
        f:scope: {}
    manager: helm
    operation: Update
    time: "2026-02-19T03:47:23Z"

Will this result in a conflict in the future? helm update manager and argocd-controller apply manager manage some shared fields.
I didn't look in such depth for the self-managed Kustomize use case, maybe we have a similar issue of multiple managers for the same fields there.

@pjiang-dev
Copy link
Copy Markdown
Contributor Author

@reggie-k
Thanks for testing that!
That makes sense that the field manager Helm is there as it still uses client-side apply. This would not be an issue, as even though both managers share fields, we use the --force-conflicts flag to apply or diff in argocd which means field conflicts are not an issue.
If for some reason there would be issues with this we can use the argocd.argoproj.io/client-side-apply-migration-manager: "helm" to transfer field ownership to argocd, as typically Helm won’t touch them again in the normal self-managed flow. Argo CD should be the only thing applying changes.

For kustomize i belive there is no field manager involved so it would behave the same as regular self-managed install.

@reggie-k
Copy link
Copy Markdown
Member

@pjiang-dev retested with Kustomize - after the migration argocd-controller manages metadata and spec and k3s manages status, so we're good here.

@reggie-k reggie-k merged commit 7180deb into argoproj:master Feb 19, 2026
27 checks passed
@reggie-k reggie-k added the cherry-pick/3.3 Candidate for cherry picking into the 3.3 release label Feb 19, 2026
argo-cd-cherry-pick-bot bot pushed a commit that referenced this pull request Feb 19, 2026
…tion (#26289)

Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
@argo-cd-cherry-pick-bot
Copy link
Copy Markdown

🍒 Cherry-pick PR created for 3.3: #26516

reggie-k pushed a commit that referenced this pull request Feb 19, 2026
…tion (cherry-pick #26289 for 3.3) (#26516)

Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
Co-authored-by: Peter Jiang <35584807+pjiang-dev@users.noreply.github.com>
devopsjedi pushed a commit to devopsjedi/argo-cd that referenced this pull request Mar 7, 2026
…tion (argoproj#26289)

Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cherry-pick/3.3 Candidate for cherry picking into the 3.3 release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] Migration to 3.3 can error on self-managed because ClientSide to ServerSideApply migrations are brittle

6 participants