Compare commits

...

360 Commits

Author SHA1 Message Date
argo-cd-cherry-pick-bot[bot]
21e13a621e fix(UI): show RollingSync step clearly when labels match no step (cherry-pick #26877 for 3.4) (#26882)
Signed-off-by: Atif Ali <atali@redhat.com>
Co-authored-by: Atif Ali <atali@redhat.com>
2026-03-17 21:41:53 -04:00
argo-cd-cherry-pick-bot[bot]
226178c1a5 fix: stack overflow when processing circular ownerrefs in resource graph (#26783) (cherry-pick #26790 for 3.4) (#26878)
Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com>
Signed-off-by: Jonathan Ogilvie <679297+jcogilvie@users.noreply.github.com>
Co-authored-by: Jonathan Ogilvie <679297+jcogilvie@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-17 22:55:48 +01:00
github-actions[bot]
d91a2ab3bf Bump version to 3.4.0-rc1 on release-3.4 branch (#26853)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: reggie-k <19544836+reggie-k@users.noreply.github.com>
2026-03-16 12:43:12 +02:00
Regina Voloshin
458837ee21 docs: clarify v prefix in cluster version related docs for CMP Plugins and CLI (#26852)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
2026-03-16 10:26:45 +00:00
Regina Voloshin
8fb91682db docs: fix cluster generator version docs (#26847)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
2026-03-16 10:30:30 +02:00
dependabot[bot]
63ddc3c3df chore(deps): bump github.com/aws/aws-sdk-go-v2/service/codecommit from 1.33.10 to 1.33.11 (#26842)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-16 09:20:01 +01:00
dependabot[bot]
b5a08fac7a chore(deps): bump renovatebot/github-action from 46.1.4 to 46.1.5 (#26839)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-16 09:19:33 +01:00
Regina Voloshin
f7dbfbd9b4 docs: updated upgrade guide 3.3-3.4 and cluster generator doc with the changed cluster version format (#26837)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
2026-03-15 21:45:50 -04:00
dudinea
f0c694d9f0 fix: fix generator bug with templating of parameters in values (#25342) (#26696)
Signed-off-by: Eugene Doudine <eugene.doudine@octopus.com>
2026-03-15 16:11:46 +02:00
dudinea
06719071d6 fix: fix GetAppdetails to show data from refs to other git repos (#26440) (#26544)
Signed-off-by: Eugene Doudine <eugene.doudine@octopus.com>
2026-03-15 16:11:03 +02:00
Michael Crenshaw
2653860882 docs: document dependency upgrade policy (#26826)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2026-03-14 13:32:55 -04:00
Oliver Gondža
59f229b9fd fix(ci): Add missing git-lfs installer checksum for ppc64le (#26835)
Signed-off-by: Oliver Gondža <ogondza@gmail.com>
2026-03-14 17:44:15 +02:00
Peter Jiang
22327073ef fix: allow automatedSyncPolicy fields to be changed to false (#26763)
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
2026-03-14 11:27:15 -04:00
Josh Soref
76a14132f5 chore: Make links accessible + friendly (#26815)
Signed-off-by: Josh Soref <jsoref@gmail.com>
2026-03-13 17:41:48 -04:00
dependabot[bot]
bd9c12cbba chore(deps): bump github.com/olekukonko/tablewriter from 1.1.3 to 1.1.4 (#26820)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-13 17:40:18 -04:00
Michael Crenshaw
d875c6170e chore: make getRepositorySecret more readable (#26827)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2026-03-13 17:08:02 -04:00
Mike Cutsail
c86e32b9d6 chore: update go-oidc to v3.17.0 (#26822)
Signed-off-by: Mike Cutsail <mcutsail15@apple.com>
2026-03-13 22:54:57 +02:00
Anudeep Reddy
e208035ac7 chore: Add C.H. Robinson to USERS.md (#26825)
Signed-off-by: Anudeep Reddy <reddanu@chrobinson.com>
2026-03-13 14:22:52 -04:00
Arthur Outhenin-Chalandre
b7e2027f35 feat: add Prune and Delete as application level sync option (#23370)
Signed-off-by: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@ledger.fr>
2026-03-13 13:50:34 -04:00
Regina Voloshin
b8e6a797cc docs: added custom health checks section to 3.3-3.4 upgrade guide (#26812)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
2026-03-13 09:31:38 +02:00
Nitish Kumar
3a4b0a0fed fix: helm flaky test (#26805)
Signed-off-by: nitishfy <justnitish06@gmail.com>
2026-03-12 12:52:33 -04:00
Anand Francis Joseph
8739f91afd fix(reposerver): using timeouts in http transport for Github App authentication (#26762)
Signed-off-by: anandf <anjoseph@redhat.com>
2026-03-12 03:15:08 -10:00
Soumya Ghosh Dastidar
6df1a5bbc2 fix: skip token refresh threshold parsing in unrelated components (#26803)
Signed-off-by: Soumya Ghosh Dastidar <gdsoumya@gmail.com>
2026-03-12 10:30:55 +00:00
Papapetrou Patroklos
d099c24655 fix: fixes the already exists error when syncing apps with replace (#26791)
Signed-off-by: Patroklos Papapetrou <ppapapetrou76@gmail.com>
2026-03-12 12:14:08 +02:00
dependabot[bot]
f1c5201e0c chore(deps): bump actions/download-artifact from 8.0.0 to 8.0.1 (#26801)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-12 09:17:34 +00:00
dependabot[bot]
4524dc997c chore(deps): bump golang.org/x/net from 0.51.0 to 0.52.0 (#26799)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-12 09:11:17 +00:00
Kirill Bilchenko
3cb4955d44 feat: expose notifications controller processors count via cmd params (#26798)
Signed-off-by: Kirill Bilchenko <kirillbilchenko@users.noreply.github.com>
2026-03-12 01:49:31 +02:00
Christopher Coco
f8c0d7efcf fix: health check doesn't detect resource deletion during sync operation (#26286)
Signed-off-by: Christopher Coco <ccoco@redhat.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2026-03-11 21:14:30 +00:00
jaehanbyun
4c59c3c7ec chore: unify clientOpts usage in command parameters (#24251)
Signed-off-by: jaehanbyun <awbrg789@naver.com>
Co-authored-by: Nitish Kumar <justnitish06@gmail.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
2026-03-11 17:09:18 +02:00
Nitish Kumar
305ecb623b fix: use certificate fingerprints to deduplicate TLS certs (#25779)
Signed-off-by: nitishfy <justnitish06@gmail.com>
2026-03-11 14:33:00 +00:00
dependabot[bot]
d1089f8b55 chore(deps): bump github.com/bradleyfalzon/ghinstallation/v2 from 2.17.0 to 2.18.0 (#26782)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-11 15:57:25 +02:00
Regina Voloshin
7477ecb5b9 ci: exclude gitops engine bumps from renovate (#26787)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
2026-03-11 09:42:00 -04:00
dependabot[bot]
79a11cb745 chore(deps): bump library/golang from e2ddb15 to c7e98cc in /test/container (#26780)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-11 12:21:18 +02:00
renovate[bot]
58993ecabc chore(deps): update docker.io/library/golang:1.26.0 docker digest to fb612b7 (#26779)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-11 12:20:50 +02:00
Nitish Kumar
7ccb6cecc1 chore(migration): migrate to aws-sdk-go-v2 (#26439)
Signed-off-by: nitishfy <justnitish06@gmail.com>
2026-03-11 12:12:56 +02:00
dependabot[bot]
6041e85df0 chore(deps): bump github.com/Azure/kubelogin from 0.2.15 to 0.2.16 (#26781)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-11 08:26:19 +01:00
Alexandre Gaudreault
95c17b68f5 test(e2e): ExpectConsistency was not consistent (#26778)
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2026-03-10 15:44:15 -04:00
Linghao Su
18fe8c4e34 chore: use server-side apply for CRDs in Tiltfile to fix annotation size limit (#26419)
Signed-off-by: linghaoSu <linghao.su@daocloud.io>
2026-03-10 19:20:28 +00:00
Michael Crenshaw
8a507b783e fix(dex): run as user 1001 (#26726) (#26775)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2026-03-10 13:08:04 -04:00
jhansi
054538b069 fix: AAD Domain Hint Improvement (fixes #18066) (#24639)
Signed-off-by: pjmanda <jhansi.manda@amadeus.com>
Signed-off-by: jhansireddy01 <m.jhansireddy01@gmail.com>
Co-authored-by: pjmanda <jhansi.manda@amadeus.com>
Co-authored-by: Nitish Kumar <justnitish06@gmail.com>
Co-authored-by: jhansireddy01 <m.jhansireddy01@gmail.com>
2026-03-10 16:21:13 +02:00
argoproj-renovate[bot]
845d1c9c40 chore(deps): update module github.com/golangci/golangci-lint/v2 to v2.11.3 (#26771)
Signed-off-by: renovate[bot] <renovate[bot]@users.noreply.github.com>
Co-authored-by: argoproj-renovate[bot] <161757507+argoproj-renovate[bot]@users.noreply.github.com>
2026-03-10 09:47:41 -04:00
Anand Francis Joseph
d9c83da78f fix(server): invalidate JWT tokens on logout (#26388)
Signed-off-by: anandf <anjoseph@redhat.com>
2026-03-10 09:03:48 -04:00
dependabot[bot]
36e8c52829 chore(deps): bump sigstore/cosign-installer from 4.0.0 to 4.1.0 (#26761)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-10 06:52:33 +02:00
Michael Crenshaw
63698bd4d2 fix(dex): run as user 1001 (#26726) (#26757)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2026-03-09 21:30:13 +00:00
S Kevin Joe Harris
cf53ed7ad1 ci: Skip CodeQL for documentation-only changes (#26602)
Signed-off-by: Kevin Joe Harris <kevinjoeharris1@gmail.com>
Signed-off-by: S Kevin Joe Harris <kevinjoeharris1@gmail.com>
Co-authored-by: rumstead <37445536+rumstead@users.noreply.github.com>
2026-03-09 15:22:59 +00:00
Michael Crenshaw
6eea558023 fix(health): use note.drySha when available (#26698)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2026-03-09 14:44:07 +00:00
Papapetrou Patroklos
6740282c3a chore: adds Pat and Reggie as release champion and approver for 3.5 (#26748)
Signed-off-by: Patroklos Papapetrou <ppapapetrou76@gmail.com>
2026-03-09 14:02:49 +02:00
Takuma Shibuya
3250327f01 fix: use InstanceName for cache cleanup on Application deletion (#26741)
Signed-off-by: takuma-shibuya <takuma.shibuya@because-i-love.dev>
Signed-off-by: sivchari <shibuuuu5@gmail.com>
2026-03-08 23:28:45 -10:00
Nitish Kumar
de99b70071 fix(reposerver): make temp dir cleanup best-effort in TestGenerateManifestsHelmWithRefs_CachedNoLsRemote (#26742)
Signed-off-by: nitishfy <justnitish06@gmail.com>
2026-03-09 07:53:00 +00:00
Alexander Matyushentsev
984a29c921 fix: skip unnecessary git state clean (#26714)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2026-03-09 12:58:31 +05:30
dependabot[bot]
92e4b2c877 chore(deps): bump golang.org/x/oauth2 from 0.35.0 to 0.36.0 (#26733)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-09 07:27:46 +00:00
dependabot[bot]
1762a59f30 chore(deps): bump the otel group with 6 updates (#26731)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: reggie-k <regina.voloshin@codefresh.io>
2026-03-09 06:49:10 +00:00
dependabot[bot]
b3c5f4b1c6 chore(deps): bump golang.org/x/sync from 0.19.0 to 0.20.0 (#26734)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-09 08:14:02 +02:00
dependabot[bot]
60ee21377c chore(deps): bump renovatebot/github-action from 46.1.3 to 46.1.4 (#26730)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-09 07:31:27 +02:00
dependabot[bot]
37f29e517d chore(deps): bump google.golang.org/grpc from 1.79.1 to 1.79.2 (#26735)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-09 07:30:21 +02:00
dependabot[bot]
fd1307d454 chore(deps): bump github.com/go-openapi/runtime from 0.29.2 to 0.29.3 (#26736)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-09 07:29:50 +02:00
dependabot[bot]
d8b33bd437 chore(deps): bump golang.org/x/time from 0.14.0 to 0.15.0 (#26737)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-09 07:28:56 +02:00
Josef Kolář
330077c5a8 fix(appset): fix post-generator selector ignoring labels in GoTemplate mode (#26717)
Signed-off-by: Josef Kolář <josef.kolar@firma.seznam.cz>
2026-03-08 22:26:11 -04:00
dependabot[bot]
0ee21afe37 chore(deps): bump library/golang from 1.26.0 to 1.26.1 in /test/container (#26708)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-08 22:12:44 -04:00
dependabot[bot]
3b34d2a56a chore(deps): bump tmp from 0.2.3 to 0.2.4 in /ui-test (#24058)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
2026-03-08 23:07:37 +01:00
tank.500m
472d50cb19 fix: OpenTelemetryCollector health check shows 0/0 for mode: daemonset (#26391)
Signed-off-by: tank.500m <tank.500m@kakaocorp.com>
2026-03-08 21:07:42 +02:00
dependabot[bot]
560d428381 chore(deps): bump docker/build-push-action from 6.19.2 to 7.0.0 (#26706)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-08 20:38:51 +02:00
argoproj-renovate[bot]
0d22f39603 chore(deps): update module github.com/vektra/mockery/v3 to v3.7.0 (#26716)
Signed-off-by: renovate[bot] <renovate[bot]@users.noreply.github.com>
Co-authored-by: argoproj-renovate[bot] <161757507+argoproj-renovate[bot]@users.noreply.github.com>
Co-authored-by: Regina Voloshin <regina.voloshin@codefresh.io>
2026-03-08 20:38:28 +02:00
Papapetrou Patroklos
08602c27c1 fix: adds the missing source-name flag in app unset command (#26712)
Signed-off-by: Patroklos Papapetrou <ppapapetrou76@gmail.com>
2026-03-08 18:11:16 +02:00
argoproj-renovate[bot]
ffeacae414 chore(deps): update module github.com/golangci/golangci-lint/v2 to v2.11.2 (#26728)
Signed-off-by: renovate[bot] <renovate[bot]@users.noreply.github.com>
Co-authored-by: argoproj-renovate[bot] <161757507+argoproj-renovate[bot]@users.noreply.github.com>
2026-03-08 17:25:16 +02:00
argoproj-renovate[bot]
1f6d54ce04 chore(deps): update module github.com/golangci/golangci-lint/v2 to v2.11.1 (#26713)
Signed-off-by: renovate[bot] <renovate[bot]@users.noreply.github.com>
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
Co-authored-by: argoproj-renovate[bot] <161757507+argoproj-renovate[bot]@users.noreply.github.com>
Co-authored-by: reggie-k <regina.voloshin@codefresh.io>
2026-03-08 15:56:45 +02:00
Rouke Broersma
ede9229353 fix(actions): Use correct annotation for CNPG suspend/resume (#26711)
Signed-off-by: Rouke Broersma <rouke.broersma@infosupport.com>
2026-03-08 15:47:43 +02:00
github-actions[bot]
d6e36fc5ea [Bot] docs: Update Snyk report (#26725)
Signed-off-by: CI <ci@argoproj.com>
Co-authored-by: CI <ci@argoproj.com>
2026-03-08 10:56:51 +00:00
Michael Crenshaw
cbbb19ddef fix: make config key optional (#26701)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2026-03-07 01:57:29 +01:00
dependabot[bot]
d8d7009a4f chore(deps): bump docker/setup-buildx-action from 3.12.0 to 4.0.0 (#26705)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-06 08:52:31 -05:00
Dan Garfield
30e30a126b docs: Update shallow clone section for clarity (#26697)
Signed-off-by: Dan Garfield <dan.garfield@octopus.com>
2026-03-06 02:06:01 +01:00
dependabot[bot]
f46c387c68 chore(deps): bump immutable from 4.0.0 to 4.3.8 in /ui (#26690)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-05 11:59:34 -05:00
dependabot[bot]
063d3b6d80 chore(deps): bump docker/setup-qemu-action from 3.6.0 to 4.0.0 (#26688)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-05 11:27:49 +02:00
dependabot[bot]
3321498f0b chore(deps): bump docker/login-action from 3.7.0 to 4.0.0 (#26689)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-05 11:27:05 +02:00
Alex Eftimie
13bc5ae0c4 feat: add argocd account session-token command (#15277) (#24638)
Signed-off-by: Alex Eftimie <alex.eftimie@getyourguide.com>
Signed-off-by: alexef <alex.eftimie@getyourguide.com>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Peter Jiang <35584807+pjiang-dev@users.noreply.github.com>
2026-03-04 13:58:11 -05:00
Mathieu Garstecki
11ec675138 docs(rbac): add note documenting the role requirement for groups (#7952) (#26672)
Signed-off-by: Mathieu Garstecki <mathieu.garstecki@pigment.com>
2026-03-04 19:39:59 +05:30
Papapetrou Patroklos
e01714590d fix: create events with argocd namespace (#26667)
Signed-off-by: Patroklos Papapetrou <ppapapetrou76@gmail.com>
2026-03-04 15:51:48 +02:00
dependabot[bot]
1f124986d9 chore(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.32.10 to 1.32.11 (#26679)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-04 13:44:54 +00:00
dependabot[bot]
abb60a9c27 chore(deps): bump github.com/aws/aws-sdk-go-v2/credentials from 1.19.10 to 1.19.11 (#26680)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-04 14:54:18 +02:00
dependabot[bot]
14e69bfa0c chore(deps): bump tj-actions/changed-files from 47.0.4 to 47.0.5 (#26676)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-04 11:56:47 +00:00
dependabot[bot]
6baa4bcbcc chore(deps): bump actions/setup-node from 6.2.0 to 6.3.0 (#26675)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-04 13:03:28 +02:00
Peter Jiang
d11c99a516 fix(ui): update AppSet UI for watch API and remove unused filters (#26631)
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
2026-03-03 08:34:56 -05:00
Aditya Raj
8ed52b2ca1 feat(notification): add appProject access to notification templates (#26437) (#26470)
Signed-off-by: Aditya Raj <adityaraj10600@gmail.com>
Signed-off-by: Aditya Raj <161347394+adityaraj178@users.noreply.github.com>
2026-03-03 07:41:05 -05:00
dependabot[bot]
0af9b6761e chore(deps): bump the otel group across 1 directory with 6 updates (#26668)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-03 13:34:16 +02:00
ManvithaP
6e89ed9867 fix: use force flag in copyutil symlink to prevent repo-server crashes (#26613)
Signed-off-by: manvitha92 <62259625+manvitha92@users.noreply.github.com>
Co-authored-by: manvitha92 <62259625+manvitha92@users.noreply.github.com>
2026-03-03 13:32:08 +02:00
Papapetrou Patroklos
7f877a68a9 chore: bumps dex version to 2.45.0 (#26609)
Signed-off-by: Patroklos Papapetrou <ppapapetrou76@gmail.com>
Signed-off-by: Papapetrou Patroklos <1743100+ppapapetrou76@users.noreply.github.com>
2026-03-03 13:07:05 +02:00
dudinea
1d2d032642 test: fix test TestUntgz/preserves file mode (#26663) (#26664)
Signed-off-by: Eugene Doudine <eugene.doudine@octopus.com>
2026-03-03 11:06:43 +02:00
Rodrigo Fior Kuntzer
b61b08d18b fix(repo-server): optimize short ref resolution in revision comparison (#26456)
Signed-off-by: Rodrigo Fior Kuntzer <rodrigo@miro.com>
2026-03-02 14:57:04 -05:00
Regina Voloshin
c85d65511b ci: run pr-title-check on pull-request (#26662)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
2026-03-02 18:12:06 +02:00
jwinters01
251c366f8a chore: bump argo-ui version (#26629)
Signed-off-by: Jonathan Winters <wintersjonathan0@gmail.com>
2026-03-02 09:21:29 -05:00
dependabot[bot]
7825b4bce3 chore(deps): bump go.opentelemetry.io/otel/sdk from 1.39.0 to 1.40.0 (#26649)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-02 12:37:29 +02:00
dependabot[bot]
5e3feb4463 chore(deps): bump renovatebot/github-action from 46.1.2 to 46.1.3 (#26658)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-02 12:36:43 +02:00
dependabot[bot]
f50f88fb66 chore(deps): bump github.com/aws/smithy-go from 1.24.1 to 1.24.2 (#26657)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-02 12:35:32 +02:00
dependabot[bot]
564d17d57f chore(deps): bump github.com/ktrysmt/go-bitbucket from 0.9.93 to 0.9.94 (#26656)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-02 12:34:56 +02:00
dependabot[bot]
91253dcf46 chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.44.0 to 1.46.0 (#26655)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-02 12:01:47 +02:00
dependabot[bot]
2c6d97a89f chore(deps): bump library/redis from 5cb00b0 to 1c054d5 in /test/container (#26654)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-02 12:01:10 +02:00
Papapetrou Patroklos
9e9a49d95f Merge pull request #26643 from malikdraz/fix/helm-version-deprecated-flag
chore(ci): remove deprecated --client flag from helm version
2026-03-01 17:38:29 +02:00
dependabot[bot]
858f159cf9 chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.43.0 to 1.44.0 (#26634)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-01 12:07:32 +02:00
Oleksandr Saulyak
a903bc46e6 fix(ui): monaco-editor search scroll positioning fix (#26638) (#26639)
Signed-off-by: oleksandr-codefresh <oleksandr.saulyak@octopus.com>
2026-03-01 11:53:35 +02:00
github-actions[bot]
945fb13fe6 [Bot] docs: Update Snyk report (#26647)
Signed-off-by: CI <ci@argoproj.com>
Co-authored-by: CI <ci@argoproj.com>
2026-03-01 09:49:02 +00:00
Papapetrou Patroklos
6a10ffe833 fix: ensure compatibility of kubeversion.version with what helm reeturns (#26469)
Signed-off-by: Patroklos Papapetrou <ppapapetrou76@gmail.com>
2026-03-01 11:40:15 +02:00
S Kevin Joe Harris
db8c801b0d docs: Add CodeQL in docs (#26645)
Signed-off-by: Kevin Joe Harris <kevinjoeharris1@gmail.com>
2026-02-28 13:54:43 -07:00
Malik Draz
739bc5812f fix: remove deprecated --client flag from helm version
The --client flag was a Helm 2 concept for distinguishing client vs
Tiller server versions. In Helm 3, there is no Tiller, so `helm version`
already only shows the client version. The flag still works but prints a
deprecation warning, adding unnecessary noise to CI output.

Signed-off-by: Malik Draz <engineering@malikdraz.io>
2026-02-28 22:45:44 +11:00
Tuxthepirate
a3b4c8327f chore: update redis-ha chart to 4.35.10 (#26453)
Signed-off-by: Doubleth1nk <20193656+Doubleth1nk@users.noreply.github.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
2026-02-27 15:03:35 -05:00
dependabot[bot]
38345d6185 chore(deps): bump actions/upload-artifact from 6.0.0 to 7.0.0 (#26633)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-27 15:02:52 -05:00
dependabot[bot]
796b722807 chore(deps): bump actions/download-artifact from 7.0.0 to 8.0.0 (#26635)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-27 15:02:31 -05:00
Jonathan Ogilvie
887736534f fix: multi-level cross-namespace hierarchy traversal for cluster-scoped intermediates (#26408, #24379) (#26410)
Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com>
Signed-off-by: Jonathan Ogilvie <679297+jcogilvie@users.noreply.github.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2026-02-27 08:07:06 -05:00
Artem Vdovin
ff8305694f fix(repo-server): optimize repoLock on checkout for manifest-generate-paths (#26468)
Signed-off-by: Artem Vdovin <arte.vdovin@gmail.com>
2026-02-26 12:15:52 -05:00
Daniel Barnes
af05c56bc4 fix(dashboards): Correct job label for the Controller Telemetry Panel (#26548)
Signed-off-by: Daniel Barnes <dabarnes2b@gmail.com>
2026-02-26 11:31:06 -05:00
Peter Jiang
19b41b9d31 feat: ApplicationSet watch API (#26409)
Signed-off-by: nitishfy <justnitish06@gmail.com>
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
Co-authored-by: nitishfy <justnitish06@gmail.com>
2026-02-26 10:07:00 -05:00
dependabot[bot]
4e71de3ef7 chore(deps): bump basic-ftp from 5.0.5 to 5.2.0 in /ui-test (#26617)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-26 09:52:42 -05:00
dependabot[bot]
b70d1444f0 chore(deps): bump minimatch from 3.1.2 to 3.1.3 in /ui (#26604)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-26 09:51:51 -05:00
dependabot[bot]
d77f8d8667 chore(deps): bump actions/setup-go from 6.2.0 to 6.3.0 (#26620)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-25 23:35:19 -10:00
dependabot[bot]
adf88c56ef chore(deps): bump github.com/alicebob/miniredis/v2 from 2.36.1 to 2.37.0 (#26621)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-25 23:34:13 -10:00
Nitish Kumar
986cdf0ef3 fix(dev): skip Tilt rebuild on test file changes (#26624)
Signed-off-by: nitishfy <justnitish06@gmail.com>
2026-02-26 13:13:32 +05:30
dependabot[bot]
98430658d8 chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.42.0 to 1.43.0 (#26622)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-26 08:38:51 +01:00
dependabot[bot]
5fff3b3640 chore(deps): bump golang.org/x/net from 0.50.0 to 0.51.0 (#26623)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-26 08:38:33 +01:00
dependabot[bot]
acc4bb7078 chore(deps): bump github.com/cloudflare/circl from 1.6.1 to 1.6.3 (#26616)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-25 22:52:55 +01:00
jwinters01
ff45972ec8 feat(ui): enable hydrator support in app create panel (#26485)
Signed-off-by: Jonathan Winters <wintersjonathan0@gmail.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2026-02-25 15:54:43 -05:00
dependabot[bot]
8c1a815b78 chore(deps): bump library/redis from dc123d5 to 5cb00b0 in /test/container (#26606)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-25 07:17:54 -05:00
argoproj-renovate[bot]
f6b0c8146f chore(deps): update docker.io/library/golang:1.26.0 docker digest to b39810f (#26603)
Signed-off-by: renovate[bot] <renovate[bot]@users.noreply.github.com>
Co-authored-by: argoproj-renovate[bot] <161757507+argoproj-renovate[bot]@users.noreply.github.com>
2026-02-25 07:17:25 -05:00
Alexander Matyushentsev
c0a2a579c5 feat: implement application cache synchronization in appset controller (#26578)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2026-02-25 01:08:53 -08:00
Takuma Shibuya
5e6449fbba fix: handle parse errors in ReadLocalConfig properly (#26597)
Signed-off-by: sivchari <shibuuuu5@gmail.com>
2026-02-24 22:40:26 -10:00
dependabot[bot]
4ffad60095 chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.41.0 to 1.42.0 (#26605)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-25 08:23:06 +01:00
Takuma Shibuya
3ce6f14b74 refactor: remove helper pointer functions in pull_request tests (#26598)
Signed-off-by: sivchari <shibuuuu5@gmail.com>
2026-02-24 13:05:53 -05:00
Takuma Shibuya
6795b80cfc refactor: replace ptr.To with new(expr) (#26534)
Signed-off-by: sivchari <shibuuuu5@gmail.com>
2026-02-24 17:42:12 +01:00
dependabot[bot]
6ab9426cf5 chore(deps): bump library/redis from 8.6.0 to 8.6.1 in /test/container (#26579)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-24 11:40:15 -05:00
argoproj-renovate[bot]
630c6e86ea chore(deps): update module github.com/vektra/mockery/v3 to v3.6.4 (#26445)
Signed-off-by: renovate[bot] <renovate[bot]@users.noreply.github.com>
Co-authored-by: argoproj-renovate[bot] <161757507+argoproj-renovate[bot]@users.noreply.github.com>
2026-02-24 15:45:19 +01:00
argoproj-renovate[bot]
51327cb818 chore(deps): update module github.com/golangci/golangci-lint/v2 to v2.10.1 (#26382)
Signed-off-by: renovate[bot] <renovate[bot]@users.noreply.github.com>
Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
Co-authored-by: argoproj-renovate[bot] <161757507+argoproj-renovate[bot]@users.noreply.github.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
2026-02-24 02:51:19 -10:00
Papapetrou Patroklos
1d50c48dec Merge pull request #26590 from sh-cho/fix-docs-link-correctly
docs: Fix link correctly
2026-02-24 13:56:21 +02:00
Seonghyeon Cho
3dd71ea14d docs: Fix link correctly
`https://www.googleapis.com/auth.admin.directory.group` is used as API
scope, not a link itself.

Signed-off-by: Seonghyeon Cho <seonghyeoncho96@gmail.com>
2026-02-24 20:40:39 +09:00
Papapetrou Patroklos
987768c07d Merge pull request #26133 from Kevinjoeharris/Fix-broken-links-in-users
docs: Fixed broken links in USERS.md
2026-02-24 12:08:12 +02:00
HARSHIL GARG
4519fdf650 fix: include Depth field in Repository.Sanitized() response (#26572)
Signed-off-by: Harshil Garg <harshil562@users.noreply.github.com>
2026-02-23 23:05:35 -10:00
Linghao Su
956a6a1352 fix(controller): handle comma-separated hook annotations for PreDelete/PostDelete hooks (#26420)
Signed-off-by: linghaoSu <linghao.su@daocloud.io>
2026-02-23 23:04:56 -10:00
dependabot[bot]
2ae64ba04b chore(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.32.9 to 1.32.10 (#26581)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-24 08:40:06 +01:00
Linghao Su
fd3c8840c9 fix(ui): remove createApplication option in write repo credential list (#23550)
Signed-off-by: linghaoSu <linghao.su@daocloud.io>
2026-02-23 16:14:37 -05:00
Oliver Gondža
5e974b03d3 docs: Proposal: Source Integrity Policies (#25148)
Signed-off-by: Oliver Gondža <ogondza@gmail.com>
Co-authored-by: jannfis <jann@mistrust.net>
2026-02-23 09:23:33 -05:00
Papapetrou Patroklos
973c3f281d Merge pull request #26569 from sh-cho/fix-docs-link
docs: Fix link
2026-02-23 13:56:17 +02:00
Seonghyeon Cho
3e29c4c752 docs: Fix link
Signed-off-by: Seonghyeon Cho <seonghyeoncho96@gmail.com>
2026-02-23 20:45:00 +09:00
dependabot[bot]
a21fcf32ae chore(deps): bump goreleaser/goreleaser-action from 6.4.0 to 7.0.0 (#26565)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-23 13:16:24 +02:00
dependabot[bot]
a8676aeb46 chore(deps): bump github.com/Azure/kubelogin from 0.2.14 to 0.2.15 (#26560)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-23 08:57:47 +01:00
dependabot[bot]
8aea5612ab chore(deps): bump github.com/ktrysmt/go-bitbucket from 0.9.91 to 0.9.93 (#26563)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-23 09:27:17 +02:00
dependabot[bot]
296100fe13 chore(deps): bump renovatebot/github-action from 46.1.1 to 46.1.2 (#26562)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-23 09:26:04 +02:00
dependabot[bot]
a4f9f57b5f chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.39.0 to 1.41.0 (#26561)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-23 09:25:33 +02:00
dependabot[bot]
09fac7b7f3 chore(deps): bump github.com/aws/smithy-go from 1.24.0 to 1.24.1 (#26564)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-23 08:17:36 +01:00
S Kevin Joe Harris
ccdcf6f885 Merge branch 'master' into Fix-broken-links-in-users 2026-02-23 01:52:36 +05:30
Sander Tervoert
7a3d6f1f6a feat: Implement nmstate health checks (#26506) (#26507)
Signed-off-by: sandert-k8s <sandert98@gmail.com>
2026-02-22 13:44:36 -05:00
Blake Pettersson
5e7bb39b02 chore: use base ref for cherry-pick prs (#26551)
Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
2026-02-22 20:34:44 +02:00
Papapetrou Patroklos
46ff85af31 Merge pull request #26546 from Kevinjoeharris/codegen-local
docs: Change codegen to codegen-local
2026-02-22 13:11:38 +02:00
Regina Voloshin
3d97fc9ede docs: instruct to enable ClientSideApplyMigration in 3.3.2 (#26547)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
2026-02-22 12:28:10 +02:00
github-actions[bot]
ee4d6e0efe [Bot] docs: Update Snyk report (#26545)
Signed-off-by: CI <ci@argoproj.com>
Co-authored-by: CI <ci@argoproj.com>
2026-02-22 10:51:59 +02:00
Kevin Joe Harris
bbb13df56f Change to make codegen-local
Signed-off-by: Kevin Joe Harris <kevinjoeharris1@gmail.com>
2026-02-22 06:49:29 +05:30
S Kevin Joe Harris
9515e68413 chore(deps): Bump create-github-app-token (#26487)
Signed-off-by: Kevin Joe Harris <kevinjoeharris1@gmail.com>
2026-02-21 18:33:58 -05:00
Papapetrou Patroklos
ae08a3ed6c Merge pull request #26519 from hokatabi/fix/kustomize-nameprefix-suffix-docs
docs(api): fix namePrefix/nameSuffix description in docs and API comments
2026-02-22 01:31:53 +02:00
dependabot[bot]
cc302bab90 chore(deps): bump sigs.k8s.io/structured-merge-diff/v6 from 6.3.1-0.20251003215857-446d8398e19c to 6.3.2 (#26332)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-21 17:41:44 -05:00
dependabot[bot]
0c2fa1ea23 chore(deps): bump github.com/redis/go-redis/v9 from 9.17.3 to 9.18.0 (#26475)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-21 17:40:35 -05:00
Rishabh Pandey
afdb3fe047 docs(operator-manual): fix typos and improve clarity (#26542)
Signed-off-by: rishabh <rishank69@gmail.com>
2026-02-21 09:18:20 -05:00
Greg Barasch
401b1a8b3c fix: parent-child httpproxy health checking (#25714)
Signed-off-by: Greg Barasch <gregbarasch@gmail.com>
2026-02-21 09:16:33 -05:00
Nitish Kumar
b85887fc3a fix: return error when cache is unavailable (#26053)
Signed-off-by: nitishfy <justnitish06@gmail.com>
2026-02-21 19:09:41 +05:30
Peter Jiang
e1aeb792a4 feat(ui): AppSet Slide Out Summary (#26490)
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
Co-authored-by: reggie-k <regina.voloshin@codefresh.io>
2026-02-20 15:15:45 -05:00
Peter Jiang
bdc3447649 fix(appset): update appset resources after creation (#26511)
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
2026-02-20 15:14:34 -05:00
dependabot[bot]
7db8ab20cb chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.36.0 to 1.39.0 (#26533)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-20 08:36:06 +01:00
shibatch
b5e09212cf chore: update generated files from codegen
Generated files updated after changing namePrefix/nameSuffix
comments in types.go to reflect override behavior.

Signed-off-by: shibatch <shibatch@pepabo.com>
2026-02-20 05:42:32 +09:00
Codey Jenkins
326831aee4 chore(docs): add 3.4 release approver and checklist (#26528)
Signed-off-by: Codey Jenkins <FourFifthsCode@users.noreply.github.com>
2026-02-19 19:04:50 +02:00
shibatch
205241f350 docs: fix namePrefix/nameSuffix description to reflect override behavior
The documentation and API comments incorrectly described namePrefix and
nameSuffix as "appended to resources", which could be misleading about
their actual behavior.

In reality, these options use `kustomize edit set nameprefix/namesuffix`
commands (util/kustomize/kustomize.go:166,175), which override any
existing namePrefix/nameSuffix values in the kustomization.yaml file.

Updated both docs/user-guide/kustomize.md and
pkg/apis/application/v1alpha1/types.go to accurately reflect this
override behavior.

Co-Authored-By: Claude (claude-sonnet-4-5) <noreply@anthropic.com>
Signed-off-by: shibatch <shibatch@pepabo.com>
2026-02-19 18:46:31 +09:00
dependabot[bot]
9851b84f97 chore(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.32.8 to 1.32.9 (#26514)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-19 08:01:17 +00:00
dependabot[bot]
f2fdc65386 chore(deps): bump github.com/aws/aws-sdk-go-v2/credentials from 1.19.8 to 1.19.9 (#26515)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-19 08:23:34 +01:00
Peter Jiang
7180deb937 fix: use csapgrade to patch managedFields for client-side apply migration (#26289)
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
2026-02-19 09:00:42 +02:00
Drew Bailey
ed6d2c525e feat(controller): Annotation to pause reconciliation for a specific cluster (#26442)
Signed-off-by: Drew Bailey <drew.bailey@airbnb.com>
Co-authored-by: Drew Bailey <drew.bailey@airbnb.com>
2026-02-18 20:30:39 -05:00
Papapetrou Patroklos
7acd9305df chore: install git-lfs 3.7.1 version using an install script (#26465)
Signed-off-by: Patroklos Papapetrou <ppapapetrou76@gmail.com>
Co-authored-by: Nitish Kumar <justnitish06@gmail.com>
2026-02-18 18:58:38 +02:00
dependabot[bot]
6a902023b2 chore(deps): bump library/ubuntu from 4095ef6 to fed6ddb in /test/container (#26494)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-18 11:08:28 -05:00
Christopher Coco
043544c197 fix: skip namespace check on cluster scoped rbac resources for auth reconcile (#26403)
Signed-off-by: Christopher Coco <ccoco@redhat.com>
2026-02-18 10:55:54 -05:00
Papapetrou Patroklos
650fa6a10e Merge pull request #26295 from jcjveraa/patch-2
docs: Add database initialization instructions example-header
2026-02-18 15:48:14 +02:00
Jaewoo Choi
03556db586 docs: update MAINTAINERS.md (#26496)
Signed-off-by: choejwoo <jaewoo45@gmail.com>
2026-02-18 12:04:09 +02:00
dependabot[bot]
47eb7ee4d6 chore(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.32.7 to 1.32.8 (#26492)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-17 23:17:31 -10:00
Rishabh P
b40a443b6a docs: fix grammar, typos, and improve clarity in documentation (#26498)
Signed-off-by: rishabh <rishank69@gmail.com>
Signed-off-by: Rishabh P <32699563+allexistence@users.noreply.github.com>
Co-authored-by: Nitish Kumar <justnitish06@gmail.com>
2026-02-17 23:13:54 -10:00
dependabot[bot]
f4852f70af chore(deps): bump github.com/aws/aws-sdk-go-v2/credentials from 1.19.7 to 1.19.8 (#26495)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-18 08:35:16 +01:00
dependabot[bot]
adbf9cd237 chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.35.0 to 1.36.0 (#26493)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-18 09:32:22 +02:00
dependabot[bot]
0f069ee767 chore(deps): bump tj-actions/changed-files from 47.0.2 to 47.0.4 (#26491)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-18 09:20:52 +02:00
Arthur Outhenin-Chalandre
a1d68ca465 fix(engine): correctly set prune confirmation message in setRunningPhase (#25915)
Signed-off-by: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@ledger.fr>
2026-02-17 09:58:49 -05:00
dependabot[bot]
3db8a412e0 chore(deps): bump actions/stale from 10.1.1 to 10.2.0 (#26474)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-16 22:04:58 -10:00
dependabot[bot]
67c5fe27cd chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.34.0 to 1.35.0 (#26476)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-16 22:04:16 -10:00
S Kevin Joe Harris
9e19a8f0bc docs: Add ci prefixes for PR titles (#26471)
Signed-off-by: Kevin Joe Harris <kevinjoeharris1@gmail.com>
2026-02-16 15:46:50 -05:00
Nitish Kumar
510af5c4d7 docs: add missing prefixes for PR titles (#26464)
Signed-off-by: nitishfy <justnitish06@gmail.com>
2026-02-16 02:37:15 -10:00
Jaewoo Choi
ac0c63eb43 chore(refactor): bump notifications-engine to include Teams adaptive card fix (#26449)
Signed-off-by: choejwoo <jaewoo45@gmail.com>
2026-02-16 10:55:24 +02:00
dependabot[bot]
8dfbdec941 chore(deps): bump google.golang.org/grpc from 1.79.0 to 1.79.1 (#26458)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-16 09:49:14 +01:00
dependabot[bot]
f1ce190671 chore(deps): bump github.com/expr-lang/expr from 1.17.7 to 1.17.8 (#26459)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-16 10:29:13 +02:00
dependabot[bot]
139ecf610b chore(deps): bump renovatebot/github-action from 46.1.0 to 46.1.1 (#26460)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-16 10:28:10 +02:00
dependabot[bot]
dcf0a1586d chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.31.0 to 1.34.0 (#26461)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-16 10:11:02 +02:00
jaehanbyun
b48ed499c0 chore(cmd): unify CLI names via common constants and simplify main dispatch (#24486)
Signed-off-by: jaehanbyun <awbrg789@naver.com>
2026-02-15 12:03:39 +01:00
S Kevin Joe Harris
b0b9658e04 chore(deps): Bump dex from v2.43.0 to v2.44.0 (#26448)
Signed-off-by: Kevin Joe Harris <kevinjoeharris1@gmail.com>
2026-02-15 11:00:45 +02:00
Jaewoo Choi
3eeebd8346 fix(docs): PR title guide from refactor to chore and reformat json (#26450)
Signed-off-by: choejwoo <jaewoo45@gmail.com>
2026-02-15 01:52:28 +01:00
S Kevin Joe Harris
2253481c84 fix(ci): Remove stale label when Issue/PR is updated (#26452)
Signed-off-by: Kevin Joe Harris <kevinjoeharris1@gmail.com>
2026-02-14 22:28:14 +01:00
rumstead
fb6a46c8de ci: upgrade codeql for go 1.26 support and give renovate post upgrade commands (#26446)
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
2026-02-13 20:26:45 +00:00
Dhruvang Makadia
86e42fb223 fix: AppProject finalizer should consider apps in all allowed namespaces (#24347) (#26416)
Signed-off-by: Dhruvang Makadia <dhruvang1@users.noreply.github.com>
2026-02-13 14:23:55 -05:00
Kanika Rana
d66ad45500 fix(docs): update other sections of feature maturity to match feature status in overview (#26411)
Signed-off-by: Kanika Rana <krana@redhat.com>
2026-02-13 14:17:53 -05:00
dependabot[bot]
5cfcd0f88f chore(deps): bump qs from 6.14.1 to 6.14.2 in /ui (#26444)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-13 12:21:49 -05:00
dependabot[bot]
c13ba1ee98 chore(deps): bump docker/build-push-action from 6.19.1 to 6.19.2 (#26433)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-13 10:17:34 -05:00
dependabot[bot]
09b3856177 chore(deps): bump google.golang.org/grpc from 1.78.0 to 1.79.0 (#26432)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-13 10:17:14 -05:00
dependabot[bot]
53a5cd3420 chore(deps): bump renovatebot/github-action from 46.0.2 to 46.1.0 (#26434)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-13 10:13:38 -05:00
dependabot[bot]
8b2ad9ba66 chore(deps): bump library/ubuntu from 25.10 to 26.04 in /test/container (#26431)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-13 10:12:52 -05:00
Papapetrou Patroklos
43ea991a25 fix: register pprof endpoints in repo-server using the params config map (#26237)
Signed-off-by: Patroklos Papapetrou <ppapapetrou76@gmail.com>
2026-02-12 11:16:17 -05:00
Linghao Su
8e636b78e5 fix(ui): add previous option to download logs functionality (#26427)
Signed-off-by: linghaoSu <linghao.su@daocloud.io>
2026-02-12 17:49:58 +02:00
Regina Voloshin
a46baf4863 ci: make Upload code coverage information to codecov.io step always run (#26379)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
2026-02-12 09:30:13 -05:00
Leonardo Luz Almeida
0cdd44bda7 chore: fix gitops-engine mod name so it can be referenced by external repos (#26407)
Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2026-02-12 09:29:40 -05:00
Nitish Kumar
18efd0cf1b fix: trim whitespaces when retrieving source refresh paths (#26400)
Signed-off-by: nitishfy <justnitish06@gmail.com>
2026-02-12 03:34:34 -10:00
dependabot[bot]
40412aaba3 chore(deps): bump docker/build-push-action from 6.18.0 to 6.19.1 (#26414)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-12 15:08:00 +02:00
dependabot[bot]
a544bc0920 chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.30.0 to 1.31.0 (#26413)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-12 12:22:18 +01:00
Papapetrou Patroklos
a2e0b6f902 chore: bumps golang version to 1.26 in all places (#26393)
Signed-off-by: Patroklos Papapetrou <ppapapetrou76@gmail.com>
Co-authored-by: Nitish Kumar <justnitish06@gmail.com>
2026-02-12 12:15:13 +02:00
Niclas Mietz
a22f33dbe2 fix(health): configconnectorcontext and configconnector (#26308) (#26309)
Signed-off-by: solidnerd <github@mietz.io>
Signed-off-by: solidnerd <niclas@mietz.io>
2026-02-11 21:04:13 +00:00
Peter Jiang
1391e2f95f feat(ui): add appset tree-view details page (#26262)
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
Signed-off-by: Peter Jiang <35584807+pjiang-dev@users.noreply.github.com>
Co-authored-by: reggie-k <regina.voloshin@codefresh.io>
Co-authored-by: Keith Chong <kykchong@redhat.com>
2026-02-11 15:52:32 -05:00
dependabot[bot]
21acbb861d chore(deps): bump library/redis from 8.2.1 to 8.2.2 in /test/container (#24859)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-11 11:28:38 -05:00
Regina Voloshin
1418e87420 ci: exclude testdata from sonar.exclusions (#26398)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
2026-02-11 09:28:54 -05:00
dependabot[bot]
e8539bea12 chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.29.0 to 1.30.0 (#26384)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-11 09:51:06 +02:00
Luis Baronceli
716339c799 fix(ui): prevent log viewer crash on malformed stream packets issue #26023 (#26226)
Signed-off-by: Luis Baronceli <luisbaronceli@gmail.com>
2026-02-11 00:43:52 +01:00
jwinters01
971bf5769a fix(ui): Parameters tab should correctly show dry source parameters (#26179)
Signed-off-by: Jonathan Winters <wintersjonathan0@gmail.com>
Signed-off-by: jwinters01 <34199886+jwinters01@users.noreply.github.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2026-02-10 16:38:23 -05:00
Linghao Su
a76a8762e4 fix(ui): standard resource icons are not displayed properly (#26216) (#26228)
Signed-off-by: linghaoSu <linghao.su@daocloud.io>
2026-02-10 16:18:39 -05:00
S Kevin Joe Harris
fdbe19adaf ci: label stale issues and PRs without auto-closing (#26318)
Signed-off-by: Kevin Joe Harris <kevinjoeharris1@gmail.com>
2026-02-10 10:56:11 -05:00
erin
8f9ee6d1da fix: compressedLayerExtracterStore+isCompressedLayer - allow tar.gzip suffixes (#26355)
Signed-off-by: erin liman <erin.liman@tiktokusds.com>
2026-02-10 10:18:50 -05:00
Regina Voloshin
9cfcd2d261 chore: placate Sonar by ignoring tetsdata files (#26371)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
2026-02-10 10:00:22 -05:00
Papapetrou Patroklos
262360e0ee chore: Bump oauth2 0.35.0 (#26347)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Patroklos Papapetrou <ppapapetrou76@gmail.com>
Signed-off-by: Papapetrou Patroklos <1743100+ppapapetrou76@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-10 16:45:46 +02:00
dudinea
6c043d3acb fix: Fix excessive ls-remote requests on monorepos with Auto Sync enabled apps (26277) (#26278)
Signed-off-by: Eugene Doudine <eugene.doudine@octopus.com>
Co-authored-by: Dan Garfield <dan.garfield@octopus.com>
2026-02-10 16:09:01 +02:00
Mike Cutsail
2793097480 feat: add OTEL instrumentation for authentication and handlers (#25296)
Signed-off-by: Mike Cutsail <mcutsail15@apple.com>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2026-02-10 13:31:55 +00:00
Matthieu MOREL
2c5f7317a5 fix: enable and fix modernize linter (#26352)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2026-02-10 08:02:55 -05:00
Regina Voloshin
66835b6ec7 chore(deps): Upgrade Kustomize to 5.8.1 (#26367)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
2026-02-10 01:24:06 -10:00
Matt Warren
d655bf6453 docs: rewrite [here] links (#26282)
Signed-off-by: Matt Warren <matt@tramat.com>
Co-authored-by: Papapetrou Patroklos <1743100+ppapapetrou76@users.noreply.github.com>
2026-02-10 16:23:55 +05:30
Matthieu MOREL
5345a2aa22 chore: update golangci-lint to v2.8.0 (#26354)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2026-02-10 16:11:02 +05:30
dependabot[bot]
89fe752eb4 chore(deps): bump golang.org/x/net from 0.49.0 to 0.50.0 (#26361)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-10 05:13:47 +00:00
dependabot[bot]
6be8ac10e6 chore(deps): bump golang.org/x/crypto from 0.47.0 to 0.48.0 (#26362)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-10 04:35:42 +00:00
dependabot[bot]
b337855e22 chore(deps): bump github.com/ktrysmt/go-bitbucket from 0.9.89 to 0.9.91 (#26360)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-10 04:01:04 +00:00
dependabot[bot]
ad186cfe54 chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.28.1 to 1.29.0 (#26358)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-10 03:58:34 +00:00
dependabot[bot]
235bf2aace chore(deps): bump golang.org/x/term from 0.39.0 to 0.40.0 (#26357)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-10 03:57:50 +00:00
dependabot[bot]
49d0b48984 chore(deps): bump tj-actions/changed-files from 47.0.1 to 47.0.2 (#26359)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-10 03:57:21 +00:00
Michael Crenshaw
8515358413 chore: improve app install ID error (#26178)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2026-02-09 17:04:59 -05:00
dependabot[bot]
2615be441d chore(deps): bump axios from 1.12.2 to 1.13.5 in /ui-test (#26353)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-09 14:11:51 -05:00
Regina Voloshin
b0488f5a9e ci: Revive CodeCov steps (#26350)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
2026-02-09 18:05:24 +00:00
Matthieu MOREL
1b4398b5ba chore(util): Fix modernize linter (#26342)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2026-02-09 10:59:51 -05:00
Matthieu MOREL
847b8b203c chore(util): Fix modernize linter (#26344)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2026-02-09 10:59:32 -05:00
Matthieu MOREL
a108a84f62 chore(server): Fix modernize linter (#26328)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2026-02-09 14:37:34 +02:00
Matthieu MOREL
27433929c0 chore(applicationset): Fix modernize linter (#26326)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2026-02-09 14:27:21 +02:00
Matthieu MOREL
1a62c87d29 chore(util): Fix modernize linter (#26316)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
2026-02-09 00:48:56 -10:00
Matthieu MOREL
34ccf865f6 chore(applicationset): Fix modernize linter (#26320)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2026-02-09 00:48:06 -10:00
Matthieu MOREL
0cff632502 chore(server): Fix modernize linter (#26324)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2026-02-09 00:47:03 -10:00
Matthieu MOREL
ac83f1d8da chore(commitserver): Fix modernize linter (#26327)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2026-02-09 00:45:44 -10:00
Matthieu MOREL
34eeede822 chore(util): Fix modernize linter (#26329)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2026-02-09 00:44:05 -10:00
github-actions[bot]
f2c69c1628 [Bot] docs: Update Snyk report (#26319)
Signed-off-by: CI <ci@argoproj.com>
Co-authored-by: CI <ci@argoproj.com>
2026-02-09 11:55:42 +02:00
dependabot[bot]
39fcff7bad chore(deps): bump renovatebot/github-action from 46.0.1 to 46.0.2 (#26336)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-09 10:20:56 +02:00
dependabot[bot]
7ccc6f94c7 chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.28.0 to 1.28.1 (#26334)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-09 10:14:07 +02:00
dependabot[bot]
9b10fe9774 chore(deps): bump github.com/ktrysmt/go-bitbucket from 0.9.88 to 0.9.89 (#26333)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-09 10:13:30 +02:00
Matthieu MOREL
76162a9310 chore(cmd): Fix modernize linter (#26321)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2026-02-08 17:51:03 +02:00
Matthieu MOREL
1d65d8be6c chore(util): Fix modernize linter (#26323)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2026-02-08 17:48:27 +02:00
Papapetrou Patroklos
2b3eae62c4 fix: fixes output of argocd proj windows list PROJ - USEANDOPERATOR was missing (#26273)
Signed-off-by: Patroklos Papapetrou <ppapapetrou76@gmail.com>
2026-02-07 18:37:31 +01:00
Matthieu MOREL
88223b09e4 chore(common): Fix modernize linter (#26312)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
2026-02-07 18:36:02 +01:00
Matthieu MOREL
0c9039ecd9 chore(controller): Fix modernize linter (#26313)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
2026-02-07 18:35:48 +01:00
Matthieu MOREL
2bea8c0deb chore(pkg): Fix modernize linter (#26314)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
2026-02-07 18:35:29 +01:00
Matthieu MOREL
342aea457f chore(reposerver): Fix modernize linter (#26315)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
2026-02-07 18:34:35 +01:00
Matthieu MOREL
6b2b0668be chore(cmpserver): Fix modernize linter (#26317)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
2026-02-07 18:31:26 +01:00
Jaewoo Choi
be08693409 fix: remove stale reposFilter references (#26310)
Signed-off-by: choejwoo <jaewoo45@gmail.com>
2026-02-07 13:19:00 +02:00
Linghao Su
24615c8ce8 fix(state): fix(controller): display correct SyncWave for hook resources #26208 (#26240)
Signed-off-by: linghaoSu <linghao.su@daocloud.io>
2026-02-07 00:28:18 +01:00
dependabot[bot]
257ebc5f3e chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.27.0 to 1.28.0 (#26292)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-06 17:18:56 -05:00
Matthieu MOREL
286c6b8725 chore(cmd): Fix modernize linter (#26298)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2026-02-06 17:18:32 -05:00
Matthieu MOREL
a369ae2cf6 chore(util): Fix modernize linter (#26300)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2026-02-06 17:17:17 -05:00
Matthieu MOREL
e2f7e7d27f chore(controller): Fix modernize linter (#26303)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2026-02-06 17:16:37 -05:00
Matthieu MOREL
6e0c949dd2 chore(hack): Fix modernize linter (#26304)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2026-02-06 17:15:45 -05:00
Jaewoo Choi
f85ad11b2a feat: remove unused reposFilter from Applications list (#24667)
Signed-off-by: choejwoo <jaewoo45@gmail.com>
2026-02-06 15:20:50 -05:00
Matthieu MOREL
2e1d81d62c chore(test): Fix modernize linter (#26301)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2026-02-06 13:56:18 -05:00
Matthieu MOREL
849815ee1a chore(applicationset): Fix modernize linter (#26299)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2026-02-06 10:16:31 -05:00
Gaston Festari
bea1139e96 docs: Typo synching -> syncing (#26275)
Signed-off-by: Gaston Festari <cilindrox@gmail.com>
2026-02-06 00:01:08 -10:00
jcjveraa
e4a97bde49 Clarify database initialization/migration section
Updated the section title and clarified the description for database initialization or migration.

Signed-off-by: jcjveraa <3942301+jcjveraa@users.noreply.github.com>
2026-02-06 09:43:55 +01:00
jcjveraa
bd284b1d29 [docs] Add database initialization instructions example-header
Add missing level 3 heade for DB example

Signed-off-by: jcjveraa <3942301+jcjveraa@users.noreply.github.com>
2026-02-06 09:22:51 +01:00
gami
b4421672f6 feat: Document and expose K8S API client environment variables(#8527) (#25145)
Signed-off-by: gami <20226196+gosarami@users.noreply.github.com>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2026-02-05 15:17:26 +00:00
Mike
96bfc1e20b fix(ui): convert yaml-editor to functional component (#24921)
Signed-off-by: Mike <mike.kangaroo.world@gmail.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2026-02-05 14:45:06 +00:00
Alex Recuenco
feab8bde77 docs: Set installation to match the quick-start guide in the installation section (#26259)
Signed-off-by: Alex Recuenco <26118630+alexrecuenco@users.noreply.github.com>
2026-02-05 09:42:09 -05:00
dependabot[bot]
9cc0c77eb5 chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.26.0 to 1.27.0 (#26267)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-05 08:37:08 +02:00
Peter Jiang
f45ee221e5 fix(appset): change appset resource status count to 5000 by default (#26249)
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
2026-02-04 21:39:01 +00:00
jwinters01
12149466c8 feat(ui): support hydrator properties in summary tab (#26152)
Signed-off-by: Jonathan Winters <wintersjonathan0@gmail.com>
Signed-off-by: jwinters01 <34199886+jwinters01@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2026-02-04 13:35:57 -05:00
Peter Jiang
84f9446d3a fix(ui): prevent crash when navigating between Applications and Appli… (#26245)
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
2026-02-04 13:21:31 -05:00
argoproj-renovate[bot]
f8cab49a07 chore(deps): update docker.io/library/golang:1.25.6 docker digest to 06d1251 (#26256)
Signed-off-by: renovate[bot] <renovate[bot]@users.noreply.github.com>
Co-authored-by: argoproj-renovate[bot] <161757507+argoproj-renovate[bot]@users.noreply.github.com>
2026-02-04 11:07:24 -05:00
argoproj-renovate[bot]
46e9022ab8 chore(deps): update docker.io/library/golang:1.25.6 docker digest to 0c87ea6 (#26235)
Signed-off-by: renovate[bot] <renovate[bot]@users.noreply.github.com>
Co-authored-by: argoproj-renovate[bot] <161757507+argoproj-renovate[bot]@users.noreply.github.com>
2026-02-04 11:05:40 +02:00
dependabot[bot]
05620cea27 chore(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.29.9 to 1.32.7 (#26254)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-04 08:49:03 +00:00
dependabot[bot]
cd65bc0585 chore(deps): bump github.com/aws/aws-sdk-go-v2/credentials from 1.17.62 to 1.19.7 (#26251)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-04 10:10:35 +02:00
dependabot[bot]
f255cef326 chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.25.0 to 1.26.0 (#26250)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-04 09:43:59 +02:00
Kanika Rana
e168d8a9fd fix: Revert "fix(ci): ensure cherry-pick commits include DCO sign-off" (#26124) (#26243) 2026-02-03 22:36:19 +00:00
Valéry Fouques
28b90a75ba fix(server): OIDC config via secrets fails (#18269) (#26214)
Signed-off-by: Valéry Fouques <48053275+BZValoche@users.noreply.github.com>
2026-02-03 16:02:25 -05:00
Regina Voloshin
7925bf7916 chore(deps): migrated aws sdk v1 to v2 for EKS with argocd-k8s-auth (#26200)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
Signed-off-by: Regina Voloshin <regina.voloshin@codefresh.io>
Co-authored-by: Papapetrou Patroklos <1743100+ppapapetrou76@users.noreply.github.com>
2026-02-03 15:56:07 -05:00
Papapetrou Patroklos
bf1f836ece fix: get app resources tree view (#26166)
Signed-off-by: Patroklos Papapetrou <ppapapetrou76@gmail.com>
2026-02-03 15:54:10 -05:00
Rohan K
ae34305d18 fix(ui): improve filter autocomplete performance for large app counts (#15087) (#26082)
Signed-off-by: Rohan K <rohankmr414@gmail.com>
2026-02-03 15:50:00 -05:00
Jaewoo Choi
d8635ca27b feat: add clear-all button to applications list filters (#26007)
Signed-off-by: choejwoo <jaewoo45@gmail.com>
2026-02-03 15:48:22 -05:00
Artem Vdovin
57e9e5e201 fix: manifest-generate-paths for multisource git+helm (#25531)
Signed-off-by: Artem Vdovin <arte.vdovin@gmail.com>
Signed-off-by: Artem Vdovin <34456690+fm1ck3y@users.noreply.github.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2026-02-03 14:57:48 +00:00
argoproj-renovate[bot]
1d66593195 chore(deps): update docker.io/library/golang:1.25.6 docker digest to 4c973c7 (#26232)
Signed-off-by: renovate[bot] <renovate[bot]@users.noreply.github.com>
Co-authored-by: argoproj-renovate[bot] <161757507+argoproj-renovate[bot]@users.noreply.github.com>
2026-02-03 10:36:40 +02:00
dependabot[bot]
01629ccd7c chore(deps): bump code.gitea.io/sdk/gitea from 0.22.1 to 0.23.2 (#26231)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-03 10:36:02 +02:00
dependabot[bot]
8ef0fd7068 chore(deps): bump library/busybox from e226d63 to b3255e7 in /test/e2e/multiarch-container (#26229)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-03 09:36:09 +02:00
Moulick Aggarwal
d883412df8 docs: Fix some admonitions in docs (#26213)
Signed-off-by: Moulick Aggarwal <Moulick@users.noreply.github.com>
Co-authored-by: Moulick Aggarwal <Moulick@users.noreply.github.com>
2026-02-02 13:58:28 -05:00
renovate[bot]
d35a2518e6 chore(deps): update docker.io/library/registry:3.0 docker digest to 6c5666b (#26217)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-02 12:37:31 -05:00
renovate[bot]
807ff53fd5 chore(deps): update dependency @types/prop-types to v15.7.15 (#26140)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-02 11:18:53 -05:00
renovate[bot]
7f34ee84fd chore(deps): update dependency @types/minimatch to v3.0.5 (#26139)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-02 11:18:30 -05:00
dependabot[bot]
a7c771fbdd chore(deps): bump renovatebot/github-action from 44.2.6 to 46.0.1 (#26203)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-02 11:37:30 +02:00
dependabot[bot]
0a70881921 chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.23.0 to 1.25.0 (#26202)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-02 09:29:39 +02:00
github-actions[bot]
e20affd6f0 [Bot] docs: Update Snyk report (#26195)
Signed-off-by: CI <ci@argoproj.com>
Co-authored-by: CI <ci@argoproj.com>
2026-02-01 14:43:32 +02:00
Peter Jiang
72085781dc feat(ui): appset list page and filters (#25837)
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
2026-01-30 13:40:38 -05:00
Jaewoo Choi
b912405c16 chore(ui): add qeId to paginate dropdown menus (#25929)
Signed-off-by: choejwoo <jaewoo45@gmail.com>
2026-01-30 13:36:33 -05:00
Jaewoo Choi
f5de841d97 fix(ui): relayout Monaco editor on window resize (#25784)
Signed-off-by: choejwoo <jaewoo45@gmail.com>
2026-01-30 13:35:58 -05:00
Jaewoo Choi
c9a5a7e62c fix(ui): make yaml editor outline button opaque (#25748)
Signed-off-by: choejwoo <jaewoo45@gmail.com>
2026-01-30 13:30:29 -05:00
Kanika Rana
989fa6fecd chore(appset): basic progressive sync e2e tests (#26092)
Signed-off-by: krana limaDocker <krana-lima-argo@example.com>
Signed-off-by: Kanika Rana <krana@redhat.com>
Co-authored-by: krana limaDocker <krana-lima-argo@example.com>
2026-01-30 16:26:57 +00:00
Codey Jenkins
28ca821978 chore(tilt): use manifest image name instead of kustomize override (#26190)
Signed-off-by: Codey Jenkins <FourFifthsCode@users.noreply.github.com>
2026-01-30 11:01:46 -05:00
dependabot[bot]
8c30738f6f chore(deps): bump actions/cache from 5.0.2 to 5.0.3 (#26183)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-30 09:25:01 -05:00
dependabot[bot]
fe93731777 chore(deps): bump github.com/golang-jwt/jwt/v5 from 5.3.0 to 5.3.1 (#26171)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-29 10:03:41 +02:00
dependabot[bot]
d064cec17a chore(deps): bump docker/login-action from 3.6.0 to 3.7.0 (#26172)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-29 10:02:20 +02:00
dependabot[bot]
e548ec76c7 chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.21.0 to 1.23.0 (#26170)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-29 10:01:14 +02:00
Aidan O'Gorman
69c2620aef docs: fixing typo in Config Management Plugins docs (#26150)
Signed-off-by: Aidan O'Gorman <aidan.ogorman@outlook.com>
2026-01-29 11:34:43 +09:00
Jaewoo Choi
2f4c5bb972 fix(ui): show filter-empty state on repos list (#26160)
Signed-off-by: choejwoo <jaewoo45@gmail.com>
2026-01-28 14:13:44 +02:00
Fan Zhang
e3f616d6dc docs: Fix wrong default value for applicationsetcontroller.enable.scm.providers (#26162)
Signed-off-by: Fan Zhang <m42zhang@uwaterloo.ca>
2026-01-28 08:49:11 +02:00
dependabot[bot]
9d459c8afe chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.19.0 to 1.21.0 (#26165)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-28 08:44:48 +02:00
Mo Sahihi Benis
7879dc0f6e docs: add SAP Signavio to USERS.md (#26164)
Signed-off-by: Mohammad Sahihi Benis <mohammad.sahihi@gmail.com>
2026-01-27 20:53:57 -05:00
Oliver Gondža
afdf99f33a fix(helm): Improve error message when helm cmd fails (#26159)
Signed-off-by: Oliver Gondža <ogondza@gmail.com>
2026-01-27 22:58:03 +02:00
Valentin Stoican
c2e594c5f5 feat: disable gRPC service config DNS TXT lookups by default (#26077)
Signed-off-by: Valentin Stoican <vstoican@ripe.net>
Co-authored-by: Valentin Stoican <vstoican@ripe.net>
2026-01-27 11:29:38 +02:00
dependabot[bot]
9c108cbaa0 chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.18.0 to 1.19.0 (#26155)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-27 11:02:27 +02:00
dependabot[bot]
e42727bcaf chore(deps): bump renovatebot/github-action from 44.2.5 to 44.2.6 (#26156)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-27 11:01:31 +02:00
Ji Kwan
5ab598e0fd feat(ui): add annotation filtering support to applications list (#25590)
Signed-off-by: Kim Jikwan <zc149@naver.com>
2026-01-27 10:59:29 +02:00
Papapetrou Patroklos
19a74df8dc fix: return missing information in cluster get API (#25566)
Signed-off-by: Patroklos Papapetrou <ppapapetrou76@gmail.com>
2026-01-26 13:37:50 -05:00
dependabot[bot]
3811a30949 chore(deps): bump github.com/bmatcuk/doublestar/v4 from 4.9.2 to 4.10.0 (#26144)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-26 08:05:12 +02:00
dependabot[bot]
928543527d chore(deps): bump github.com/redis/go-redis/v9 from 9.17.2 to 9.17.3 (#26145)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-26 08:04:44 +02:00
dependabot[bot]
e10a395f34 chore(deps): bump github.com/alicebob/miniredis/v2 from 2.36.0 to 2.36.1 (#26146)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-26 08:03:59 +02:00
dependabot[bot]
c7574970d0 chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.16.0 to 1.18.0 (#26143)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-26 08:03:29 +02:00
github-actions[bot]
24434907af [Bot] docs: Update Snyk report (#26138)
Signed-off-by: CI <ci@argoproj.com>
Co-authored-by: CI <ci@argoproj.com>
2026-01-25 12:06:36 +02:00
renovate[bot]
988e4f48cf chore(deps): update docker.io/library/ubuntu:25.10 docker digest to 4a9232c (#26131)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-25 08:25:11 +02:00
renovate[bot]
82be819e9a chore(deps): update docker.io/library/redis:8.2.3 docker digest to c4316c4 (#26130)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-25 08:24:27 +02:00
dudinea
aadf2af7e1 fix(ci): fix deleting files on linux in make build-ui (#26134) (#26135)
Signed-off-by: Eugene Doudine <eugene.doudine@octopus.com>
2026-01-25 08:23:42 +02:00
Anagha S Devan
92c5389388 fix(ci): ensure cherry-pick commits include DCO sign-off (#26124)
Signed-off-by: Anagha S Devan <anaghaavi176@gmail.com>
2026-01-25 08:23:06 +02:00
Kevin Joe Harris
d60b41da5e Fixed broken links in USERS.md
Signed-off-by: Kevin Joe Harris <kevinjoeharris1@gmail.com>
2026-01-24 22:07:04 +05:30
renovate[bot]
81d109fb7a chore(deps): update dependency @types/deepmerge to v2.2.3 (#25609)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-23 16:07:46 -05:00
renovate[bot]
3ddf722517 chore(deps): update dependency @codecov/webpack-plugin to v0.0.1-beta.12 (#25385)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-23 16:07:09 -05:00
Michael Crenshaw
65350789e8 docs: small fixes for mkdocs warnings (#26112)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Nitish Kumar <justnitish06@gmail.com>
2026-01-23 13:00:47 +00:00
dependabot[bot]
82ee09a930 chore(deps): bump library/busybox from b86c79d to e226d63 in /test/e2e/multiarch-container (#26122)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-23 07:34:09 -05:00
dependabot[bot]
4e827c80cf chore(deps): bump actions/checkout from 6.0.1 to 6.0.2 (#26123)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-23 01:34:11 -10:00
Alexandre Gaudreault
4d66a209d3 fix: consider Replace/Force sync option on live resource annotations (#26110)
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2026-01-22 17:19:45 -05:00
Michael Crenshaw
3e26594009 docs: cherry-pick process (#26109)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2026-01-22 12:28:52 -05:00
Christian Oleson
90ce1782ec docs: Add Imagine Learning to USERS.md (#26111)
Signed-off-by: Christian Oleson <Christian.Oleson@ImagineLearning.com>
2026-01-22 11:14:26 -05:00
Codey Jenkins
e5e00d3f6f fix(hydrator): use refresh paths from drySource when source hydration is enabled (#25516)
Signed-off-by: Codey Jenkins <FourFifthsCode@users.noreply.github.com>
Signed-off-by: pbhatnagar-oss <pbhatifiwork@gmail.com>
Co-authored-by: pbhatnagar-oss <pbhatifiwork@gmail.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2026-01-22 15:08:58 +00:00
dependabot[bot]
559dc16e72 chore(deps): bump lodash from 4.17.21 to 4.17.23 in /ui (#26100)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-22 10:44:12 +02:00
renovate[bot]
1b85a688ac chore(deps): update dependency lodash-es to v4.17.23 [security] (#26099)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-22 10:43:07 +02:00
dependabot[bot]
9182e6696f chore(deps): bump github.com/alicebob/miniredis/v2 from 2.35.0 to 2.36.0 (#26103)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-22 10:36:52 +02:00
dependabot[bot]
1a1b142cea chore(deps): bump library/busybox from 2383baa to b86c79d in /test/e2e/multiarch-container (#26101)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-22 08:40:37 +02:00
dependabot[bot]
5c2a417257 chore(deps): bump peter-evans/create-pull-request from 8.0.0 to 8.1.0 (#26102)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-22 08:39:51 +02:00
dudinea
6a597c9e62 chore: fix make test running all the gitops-engine tests when requested to test specific ArgoCD module (#26089) (#26090)
Signed-off-by: Eugene Doudine <eugene.doudine@octopus.com>
2026-01-21 18:08:41 +02:00
Regina Voloshin
e8895b8d68 ci: test against k8s 1.35.0 (#26062)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
2026-01-21 10:47:55 -05:00
S Kevin Joe Harris
b8d4216438 docs: Fixed broken links (#26083)
Signed-off-by: Kevin Joe Harris <kevinjoeharris1@gmail.com>
Signed-off-by: S Kevin Joe Harris <59595928+Kevinjoeharris@users.noreply.github.com>
Co-authored-by: Regina Voloshin <regina.voloshin@codefresh.io>
2026-01-21 16:49:35 +02:00
Aditya Raj
507289925b feat(hydrator): making configurable authorName/Email used for hydration commit (#22847) (#25746)
Signed-off-by: Aditya Raj <adityaraj10600@gmail.com>
2026-01-21 08:44:32 -05:00
Kostis (Octopus Deploy)
fc6379b90e docs: recommend cluster generator in cluster boostrapping page (#26084)
Signed-off-by: Kostis Kapelonis <kostis.kapelonis@octopus.com>
2026-01-21 14:16:27 +02:00
dependabot[bot]
c626b202b7 chore(deps): bump gitlab.com/gitlab-org/api/client-go from 1.14.0 to 1.16.0 (#26081)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-21 07:26:27 +00:00
Aditya Raj
2f7d36bc38 fix: resolve flaky TestSync_SyncWaveHookError test (#26080)
Signed-off-by: Aditya Raj <adityaraj10600@gmail.com>
2026-01-21 09:19:39 +02:00
John Soutar
c879b6da2f chore(deps): update notifications-engine to fix GitHub PR comments nil panic (#26065)
Signed-off-by: John Soutar <john@tella.com>
2026-01-20 15:45:32 +02:00
dudinea
4e997f0d5e fix: invalid error message on health check failure (#26040) (#26039)
Signed-off-by: Eugene Doudine <eugene.doudine@octopus.com>
2026-01-20 11:24:47 +02:00
dependabot[bot]
8b1415a6b7 chore(deps): bump renovatebot/github-action from 44.2.4 to 44.2.5 (#26059)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-20 10:41:03 +02:00
argoproj-renovate[bot]
acb30b4e06 chore(deps): update docker.io/library/golang:1.25.6 docker digest to ce63a16 (#26056)
Signed-off-by: renovate[bot] <renovate[bot]@users.noreply.github.com>
Co-authored-by: argoproj-renovate[bot] <161757507+argoproj-renovate[bot]@users.noreply.github.com>
2026-01-20 08:11:08 +02:00
Yugan
408e99e9e9 feat: Allow custom User-Agent headers for Helm repository requests (#25473)
Signed-off-by: Yugan <yugannkt@gmail.com>
2026-01-19 12:06:09 -05:00
Alexandre Gaudreault
228378474a fix(hooks): always remove finalizers (#23226) (#25916)
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Leonardo Luz Almeida <leoluz@users.noreply.github.com>
2026-01-19 16:42:03 +00:00
Nitish Kumar
a66fe2af24 docs: add information on handling ambiguous revisions (#26052)
Signed-off-by: nitishfy <justnitish06@gmail.com>
Signed-off-by: Nitish Kumar <justnitish06@gmail.com>
Co-authored-by: Afzal Ansari <afzal442@gmail.com>
2026-01-19 13:46:43 +00:00
Regina Voloshin
088ef94d78 docs: change manifests master reference to stable reference (#26035)
Signed-off-by: renovate[bot] <renovate[bot]@users.noreply.github.com>
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
Co-authored-by: argoproj-renovate[bot] <161757507+argoproj-renovate[bot]@users.noreply.github.com>
2026-01-19 17:04:25 +05:30
José Maia
b911650616 docs: Fix typo in Plugin generator description (#26051)
Signed-off-by: José Maia <josecbmaia@hotmail.com>
2026-01-19 16:57:42 +05:30
726 changed files with 81847 additions and 46467 deletions

View File

@@ -4,6 +4,7 @@ module.exports = {
autodiscover: false,
allowPostUpgradeCommandTemplating: true,
allowedPostUpgradeCommands: ["make mockgen"],
binarySource: 'install',
extends: [
"github>argoproj/argo-cd//renovate-presets/commons.json5",
"github>argoproj/argo-cd//renovate-presets/custom-managers/shell.json5",

View File

@@ -1,15 +1,15 @@
{
"LABEL": {
"name": "title needs formatting",
"color": "EEEEEE"
},
"CHECKS": {
"prefixes": ["[Bot] docs: "],
"regexp": "^(feat|fix|docs|test|ci|chore)!?(\\(.*\\))?!?:.*"
},
"MESSAGES": {
"success": "PR title is valid",
"failure": "PR title is invalid",
"notice": "PR Title needs to pass regex '^(feat|fix|docs|test|ci|chore)!?(\\(.*\\))?!?:.*"
}
"LABEL": {
"name": "title needs formatting",
"color": "EEEEEE"
},
"CHECKS": {
"prefixes": ["[Bot] docs: "],
"regexp": "^(refactor|feat|fix|docs|test|ci|chore)!?(\\(.*\\))?!?:.*"
},
"MESSAGES": {
"success": "PR title is valid",
"failure": "PR title is invalid",
"notice": "PR Title needs to pass regex '^(refactor|feat|fix|docs|test|ci|chore)!?(\\(.*\\))?!?:.*"
}
}

View File

@@ -11,6 +11,7 @@
| release.yaml | Build images, cli-binaries, provenances, and post actions |
| scorecard.yaml | Generate scorecard for supply-chain security |
| update-snyk.yaml | Scheduled snyk reports |
| stale.yaml | Labels stale issues and PRs |
# Reusable workflows

View File

@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
@@ -37,7 +37,7 @@ jobs:
working-directory: /home/runner/go/src/github.com/argoproj/argo-cd
- name: Setup Golang
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Add ~/go/bin to PATH
@@ -74,7 +74,7 @@ jobs:
rsync -a --exclude=.git /home/runner/go/src/github.com/argoproj/argo-cd/ ../argo-cd
- name: Create pull request
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
with:
commit-message: "Bump major version to ${{ steps.get-target-version.outputs.TARGET_VERSION }}"
title: "Bump major version to ${{ steps.get-target-version.outputs.TARGET_VERSION }}"

View File

@@ -32,13 +32,13 @@ jobs:
steps:
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1
uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
with:
app-id: ${{ secrets.CHERRYPICK_APP_ID }}
private-key: ${{ secrets.CHERRYPICK_APP_PRIVATE_KEY }}
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
token: ${{ steps.generate-token.outputs.token }}

View File

@@ -14,7 +14,7 @@ on:
env:
# Golang version to use across CI steps
# renovate: datasource=golang-version packageName=golang
GOLANG_VERSION: '1.25.6'
GOLANG_VERSION: '1.26.0'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
@@ -31,8 +31,8 @@ jobs:
frontend: ${{ steps.filter.outputs.frontend_any_changed }}
docs: ${{ steps.filter.outputs.docs_any_changed }}
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891 # v47.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
id: filter
with:
# Any file which is not under docs/, ui/ or is not a markdown file is counted as a backend file
@@ -55,9 +55,9 @@ jobs:
- changes
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Golang
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Download all Go modules
@@ -75,13 +75,13 @@ jobs:
- changes
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Golang
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Restore go build cache
uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -102,16 +102,16 @@ jobs:
- changes
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Golang
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Run golangci-lint
uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0
with:
# renovate: datasource=go packageName=github.com/golangci/golangci-lint versioning=regex:^v(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)?$
version: v2.5.0
# renovate: datasource=go packageName=github.com/golangci/golangci-lint/v2 versioning=regex:^v(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)?$
version: v2.11.3
args: --verbose
test-go:
@@ -128,11 +128,11 @@ jobs:
- name: Create checkout directory
run: mkdir -p ~/go/src/github.com/argoproj
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Create symlink in GOPATH
run: ln -s $(pwd) ~/go/src/github.com/argoproj/argo-cd
- name: Setup Golang
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Install required packages
@@ -152,7 +152,7 @@ jobs:
run: |
echo "/usr/local/bin" >> $GITHUB_PATH
- name: Restore go build cache
uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -173,7 +173,7 @@ jobs:
- name: Run all unit tests
run: make test-local
- name: Generate test results artifacts
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: test-results
path: test-results
@@ -192,11 +192,11 @@ jobs:
- name: Create checkout directory
run: mkdir -p ~/go/src/github.com/argoproj
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Create symlink in GOPATH
run: ln -s $(pwd) ~/go/src/github.com/argoproj/argo-cd
- name: Setup Golang
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Install required packages
@@ -216,7 +216,7 @@ jobs:
run: |
echo "/usr/local/bin" >> $GITHUB_PATH
- name: Restore go build cache
uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -237,7 +237,7 @@ jobs:
- name: Run all unit tests
run: make test-race-local
- name: Generate test results artifacts
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: race-results
path: test-results/
@@ -250,9 +250,9 @@ jobs:
- changes
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Golang
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Create symlink in GOPATH
@@ -307,15 +307,15 @@ jobs:
- changes
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup NodeJS
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
# renovate: datasource=node-version packageName=node versioning=node
node-version: '22.9.0'
- name: Restore node dependency cache
id: cache-dependencies
uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ui/node_modules
key: ${{ runner.os }}-node-dep-v2-${{ hashFiles('**/yarn.lock') }}
@@ -340,7 +340,7 @@ jobs:
shellcheck:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- run: |
sudo apt-get install shellcheck
shellcheck -e SC2059 -e SC2154 -e SC2034 -e SC2016 -e SC1091 $(find . -type f -name '*.sh' | grep -v './ui/node_modules') | tee sc.log
@@ -360,32 +360,28 @@ jobs:
codecov_secret: ${{ secrets.CODECOV_TOKEN }}
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- name: Restore node dependency cache
id: cache-dependencies
uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ui/node_modules
key: ${{ runner.os }}-node-dep-v2-${{ hashFiles('**/yarn.lock') }}
if: env.codecov_secret != ''
- name: Remove other node_modules directory
run: |
rm -rf ui/node_modules/argo-ui/node_modules
if: env.codecov_secret != ''
- name: Get e2e code coverage
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: e2e-code-coverage
path: e2e-code-coverage
if: env.codecov_secret != ''
- name: Get unit test code coverage
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: test-results
path: test-results
if: env.codecov_secret != ''
- name: combine-go-coverage
# We generate coverage reports for all Argo CD components, but only the applicationset-controller,
# app-controller, repo-server, and commit-server report contain coverage data. The other components currently
@@ -393,18 +389,18 @@ jobs:
# references to their coverage output directories.
run: |
go tool covdata percent -i=test-results,e2e-code-coverage/applicationset-controller,e2e-code-coverage/repo-server,e2e-code-coverage/app-controller,e2e-code-coverage/commit-server -o test-results/full-coverage.out
if: env.codecov_secret != ''
- name: Upload code coverage information to codecov.io
# Only run when the workflow is for upstream (PR target or push is in argoproj/argo-cd).
if: github.repository == 'argoproj/argo-cd'
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
with:
files: test-results/full-coverage.out
fail_ci_if_error: true
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
if: env.codecov_secret != ''
- name: Upload test results to Codecov
# Codecov uploads test results to Codecov.io on upstream master branch and on fork master branch if the token is configured.
if: env.codecov_secret != '' && github.ref == 'refs/heads/master' && github.event_name == 'push'
# Codecov uploads test results to Codecov.io on upstream master branch.
if: github.repository == 'argoproj/argo-cd' && github.ref == 'refs/heads/master' && github.event_name == 'push'
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
with:
files: test-results/junit.xml
@@ -427,14 +423,14 @@ jobs:
# latest: true means that this version mush upload the coverage report to codecov.io
# We designate the latest version because we only collect code coverage for that version.
k3s:
- version: v1.34.2
- version: v1.35.0
latest: true
- version: v1.34.2
latest: false
- version: v1.33.1
latest: false
- version: v1.32.1
latest: false
- version: v1.31.0
latest: false
needs:
- build-go
- changes
@@ -456,9 +452,9 @@ jobs:
swap-storage: false
tool-cache: false
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Golang
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Set GOPATH
@@ -480,7 +476,7 @@ jobs:
sudo chmod go-r $HOME/.kube/config
kubectl version
- name: Restore go build cache
uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -506,7 +502,7 @@ jobs:
git config --global user.email "john.doe@example.com"
- name: Pull Docker image required for tests
run: |
docker pull ghcr.io/dexidp/dex:v2.43.0
docker pull ghcr.io/dexidp/dex:v2.45.0
docker pull argoproj/argo-cd-ci-builder:v1.0.0
docker pull redis:8.2.3-alpine
- name: Create target directory for binaries in the build-process
@@ -538,13 +534,13 @@ jobs:
goreman run stop-all || echo "goreman trouble"
sleep 30
- name: Upload e2e coverage report
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: e2e-code-coverage
path: /tmp/coverage
if: ${{ matrix.k3s.latest }}
- name: Upload e2e-server logs
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: e2e-server-k8s${{ matrix.k3s.version }}.log
path: /tmp/e2e-server.log

View File

@@ -6,7 +6,18 @@ on:
branches-ignore:
- 'dependabot/**'
- 'cherry-pick-*'
# Skip CodeQL for documentation-only changes
paths-ignore:
- '**.md'
- 'docs/**'
pull_request:
# Skip CodeQL for documentation-only changes
paths-ignore:
- '*.md'
- '**/*.md'
- 'docs/assets/**'
schedule:
- cron: '0 19 * * 0'
@@ -29,11 +40,11 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# Use correct go version. https://github.com/github/codeql-action/issues/1842#issuecomment-1704398087
- name: Setup Golang
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version-file: go.mod

View File

@@ -56,27 +56,27 @@ jobs:
image-digest: ${{ steps.image.outputs.digest }}
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
if: ${{ github.ref_type == 'tag'}}
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
if: ${{ github.ref_type != 'tag'}}
- name: Setup Golang
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version: ${{ inputs.go-version }}
cache: false
- name: Install cosign
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0
- uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
- uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
- uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Setup tags for container image as a CSV type
run: |
@@ -103,7 +103,7 @@ jobs:
echo 'EOF' >> $GITHUB_ENV
- name: Login to Quay.io
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with:
registry: quay.io
username: ${{ secrets.quay_username }}
@@ -111,7 +111,7 @@ jobs:
if: ${{ inputs.quay_image_name && inputs.push }}
- name: Login to GitHub Container Registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with:
registry: ghcr.io
username: ${{ secrets.ghcr_username }}
@@ -119,7 +119,7 @@ jobs:
if: ${{ inputs.ghcr_image_name && inputs.push }}
- name: Login to dockerhub Container Registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with:
username: ${{ secrets.docker_username }}
password: ${{ secrets.docker_password }}
@@ -142,7 +142,7 @@ jobs:
- name: Build and push container image
id: image
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 #v6.18.0
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 #v7.0.0
with:
context: .
platforms: ${{ inputs.platforms }}

View File

@@ -31,7 +31,7 @@ jobs:
ghcr_provenance_image: ${{ steps.image.outputs.ghcr_provenance_image }}
allow_ghcr_publish: ${{ steps.image.outputs.allow_ghcr_publish }}
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set image tag and names
run: |
@@ -86,7 +86,7 @@ jobs:
with:
# Note: cannot use env variables to set go-version (https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations)
# renovate: datasource=golang-version packageName=golang
go-version: 1.25.6
go-version: 1.26.0
platforms: ${{ needs.set-vars.outputs.platforms }}
push: false
@@ -103,7 +103,7 @@ jobs:
ghcr_image_name: ${{ needs.set-vars.outputs.ghcr_image_name }}
# Note: cannot use env variables to set go-version (https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations)
# renovate: datasource=golang-version packageName=golang
go-version: 1.25.6
go-version: 1.26.0
platforms: ${{ needs.set-vars.outputs.platforms }}
push: true
secrets:
@@ -140,7 +140,7 @@ jobs:
if: ${{ github.repository == 'argoproj/argo-cd' && github.event_name == 'push' }}
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- run: git clone "https://$TOKEN@github.com/argoproj/argoproj-deployments"
env:
TOKEN: ${{ secrets.TOKEN }}

View File

@@ -29,7 +29,7 @@ jobs:
IMAGE_REPOSITORY: ${{ vars.IMAGE_REPOSITORY || 'argocd' }}
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
@@ -70,7 +70,7 @@ jobs:
git stash pop
- name: Create pull request
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
with:
commit-message: "Bump version to ${{ inputs.TARGET_VERSION }}"
title: "Bump version to ${{ inputs.TARGET_VERSION }} on ${{ inputs.TARGET_BRANCH }} branch"

View File

@@ -1,11 +1,9 @@
name: "Lint PR"
on:
pull_request_target:
pull_request:
types: [opened, edited, reopened, synchronize]
# IMPORTANT: No checkout actions, scripts, or builds should be added to this workflow. Permissions should always be used
# with extreme caution. https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target
permissions: {}
# PR updates can happen in quick succession leading to this

View File

@@ -11,7 +11,7 @@ permissions: {}
env:
# renovate: datasource=golang-version packageName=golang
GOLANG_VERSION: '1.25.6' # Note: go-version must also be set in job argocd-image.with.go-version
GOLANG_VERSION: '1.26.0' # Note: go-version must also be set in job argocd-image.with.go-version
jobs:
argocd-image:
@@ -26,7 +26,7 @@ jobs:
quay_image_name: ${{ needs.setup-variables.outputs.quay_image_name }}
# Note: cannot use env variables to set go-version (https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations)
# renovate: datasource=golang-version packageName=golang
go-version: 1.25.6
go-version: 1.26.0
platforms: linux/amd64,linux/arm64,linux/s390x,linux/ppc64le
push: true
secrets:
@@ -48,7 +48,7 @@ jobs:
allow_fork_release: ${{ steps.var.outputs.allow_fork_release }}
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
@@ -124,7 +124,7 @@ jobs:
hashes: ${{ steps.hash.outputs.hashes }}
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
@@ -133,7 +133,7 @@ jobs:
run: git fetch --force --tags
- name: Setup Golang
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version: ${{ env.GOLANG_VERSION }}
cache: false
@@ -159,7 +159,7 @@ jobs:
tool-cache: false
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0
uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0
id: run-goreleaser
with:
version: latest
@@ -213,13 +213,13 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Golang
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version: ${{ env.GOLANG_VERSION }}
cache: false
@@ -300,7 +300,7 @@ jobs:
TAG_STABLE: ${{ needs.setup-variables.outputs.is_latest_release }}
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
@@ -344,7 +344,7 @@ jobs:
if: ${{ env.UPDATE_VERSION == 'true' }}
- name: Create PR to update VERSION on master branch
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
with:
commit-message: Bump version in master
title: 'chore: Bump version in master'

View File

@@ -20,17 +20,10 @@ jobs:
private-key: ${{ secrets.RENOVATE_APP_PRIVATE_KEY }}
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # 6.0.1
# Some codegen commands require Go to be setup
- name: Setup Golang
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
with:
# renovate: datasource=golang-version packageName=golang
go-version: 1.25.6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2
- name: Self-hosted Renovate
uses: renovatebot/github-action@66387ab8c2464d575b933fa44e9e5a86b2822809 #44.2.4
uses: renovatebot/github-action@abd08c7549b2a864af5df4a2e369c43f035a6a9d #46.1.5
with:
configurationFile: .github/configs/renovate-config.js
token: '${{ steps.get_token.outputs.token }}'

View File

@@ -30,7 +30,7 @@ jobs:
steps:
- name: "Checkout code"
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
@@ -54,7 +54,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: SARIF file
path: results.sarif

33
.github/workflows/stale.yaml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: "Label stale issues and PRs"
on:
schedule:
- cron: "0 0 * * *" #Runs midnight 12AM UTC
#Added Recommended permissions
permissions:
issues: write
pull-requests: write
jobs:
stale:
runs-on: ubuntu-24.04
steps:
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: >
This issue has been marked as stale because it has had no activity for 90 days. Please comment if this is still relevant.
stale-pr-message: >
This pull request has been marked as stale because it has had no activity for 90 days. Please comment if this is still relevant.
days-before-stale: 90
days-before-close: -1 # Auto-close diabled
exempt-issue-labels: >
bug, security, breaking/high, breaking/medium, breaking/low
# General configuration
operations-per-run: 200
remove-stale-when-updated: true #Remove stale label when issue/pr is updated

View File

@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Build reports

View File

@@ -22,6 +22,7 @@ linters:
- govet
- importas
- misspell
- modernize
- noctx
- perfsprint
- revive
@@ -121,6 +122,13 @@ linters:
- pkg: github.com/argoproj/argo-cd/v3/util/io
alias: utilio
modernize:
disable:
# Suggest replacing omitempty with omitzero for struct fields.
- omitzero
# Simplify code by using go1.26's new(expr). - generates lots of false positives.
- newexpr
nolintlint:
require-specific: true

View File

@@ -46,7 +46,7 @@ packages:
interfaces:
RepoServerServiceClient: {}
RepoServerService_GenerateManifestWithFilesClient: {}
github.com/argoproj/argo-cd/v3/server/application:
github.com/argoproj/argo-cd/v3/server/broadcast:
interfaces:
Broadcaster: {}
github.com/argoproj/argo-cd/v3/server/extension:
@@ -79,10 +79,10 @@ packages:
github.com/argoproj/argo-cd/v3/util/workloadidentity:
interfaces:
TokenProvider: {}
github.com/argoproj/gitops-engine/pkg/cache:
github.com/argoproj/argo-cd/gitops-engine/pkg/cache:
interfaces:
ClusterCache: {}
github.com/argoproj/gitops-engine/pkg/diff:
github.com/argoproj/argo-cd/gitops-engine/pkg/diff:
interfaces:
ServerSideDryRunner: {}
github.com/microsoft/azure-devops-go-api/azuredevops/v7/git:

View File

@@ -1,10 +1,10 @@
ARG BASE_IMAGE=docker.io/library/ubuntu:25.10@sha256:5922638447b1e3ba114332c896a2c7288c876bb94adec923d70d58a17d2fec5e
ARG BASE_IMAGE=docker.io/library/ubuntu:25.10@sha256:4a9232cc47bf99defcc8860ef6222c99773330367fcecbf21ba2edb0b810a31e
####################################################################################################
# Builder image
# Initial stage which pulls prepares build dependencies and CLI tooling we need for our final image
# Also used as the image in CI jobs so needs all dependencies
####################################################################################################
FROM docker.io/library/golang:1.25.6@sha256:fc24d3881a021e7b968a4610fc024fba749f98fe5c07d4f28e6cfa14dc65a84c AS builder
FROM docker.io/library/golang:1.26.0@sha256:fb612b7831d53a89cbc0aaa7855b69ad7b0caf603715860cf538df854d047b84 AS builder
WORKDIR /tmp
@@ -16,7 +16,6 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
unzip \
fcgiwrap \
git \
git-lfs \
make \
wget \
gcc \
@@ -29,7 +28,8 @@ COPY hack/install.sh hack/tool-versions.sh ./
COPY hack/installers installers
RUN ./install.sh helm && \
INSTALL_PATH=/usr/local/bin ./install.sh kustomize
INSTALL_PATH=/usr/local/bin ./install.sh kustomize && \
./install.sh git-lfs
####################################################################################################
# Argo CD Base - used as the base for both the release and dev argocd images
@@ -51,7 +51,7 @@ RUN groupadd -g $ARGOCD_USER_ID argocd && \
apt-get update && \
apt-get dist-upgrade -y && \
apt-get install --no-install-recommends -y \
git git-lfs tini ca-certificates gpg gpg-agent tzdata connect-proxy openssh-client && \
git tini ca-certificates gpg gpg-agent tzdata connect-proxy openssh-client && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*
@@ -61,6 +61,7 @@ COPY hack/gpg-wrapper.sh \
/usr/local/bin/
COPY --from=builder /usr/local/bin/helm /usr/local/bin/helm
COPY --from=builder /usr/local/bin/kustomize /usr/local/bin/kustomize
COPY --from=builder /usr/local/bin/git-lfs /usr/local/bin/git-lfs
# keep uid_entrypoint.sh for backward compatibility
RUN ln -s /usr/local/bin/entrypoint.sh /usr/local/bin/uid_entrypoint.sh
@@ -79,6 +80,12 @@ RUN mkdir -p tls && \
ENV USER=argocd
# Disable gRPC service config lookups via DNS TXT records to prevent excessive
# DNS queries for _grpc_config.<hostname> which can cause timeouts in dual-stack
# environments. This can be overridden via argocd-cmd-params-cm ConfigMap.
# See https://github.com/argoproj/argo-cd/issues/24991
ENV GRPC_ENABLE_TXT_SERVICE_CONFIG=false
USER $ARGOCD_USER_ID
WORKDIR /home/argocd
@@ -103,7 +110,7 @@ RUN HOST_ARCH=$TARGETARCH NODE_ENV='production' NODE_ONLINE_ENV='online' NODE_OP
####################################################################################################
# Argo CD Build stage which performs the actual build of Argo CD binaries
####################################################################################################
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.25.6@sha256:fc24d3881a021e7b968a4610fc024fba749f98fe5c07d4f28e6cfa14dc65a84c AS argocd-build
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.26.0@sha256:fb612b7831d53a89cbc0aaa7855b69ad7b0caf603715860cf538df854d047b84 AS argocd-build
WORKDIR /go/src/github.com/argoproj/argo-cd

View File

@@ -1,4 +1,4 @@
FROM docker.io/library/golang:1.25.6@sha256:fc24d3881a021e7b968a4610fc024fba749f98fe5c07d4f28e6cfa14dc65a84c
FROM docker.io/library/golang:1.26.0@sha256:fb612b7831d53a89cbc0aaa7855b69ad7b0caf603715860cf538df854d047b84
ENV DEBIAN_FRONTEND=noninteractive
@@ -11,7 +11,6 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
unzip \
fcgiwrap \
git \
git-lfs \
make \
wget \
gcc \
@@ -28,7 +27,8 @@ COPY hack/install.sh hack/tool-versions.sh ./
COPY hack/installers installers
RUN ./install.sh helm && \
INSTALL_PATH=/usr/local/bin ./install.sh kustomize
INSTALL_PATH=/usr/local/bin ./install.sh kustomize && \
./install.sh git-lfs
COPY hack/gpg-wrapper.sh \
hack/git-verify-wrapper.sh \

View File

@@ -18,14 +18,14 @@ This document lists the maintainers of the Argo CD project.
| Dan Garfield | [todaywasawesome](https://github.com/todaywasawesome) | Approver(docs) | [Octopus Deploy](https://octopus.com/) |
| Alexandre Gaudreault | [agaudreault](https://github.com/agaudreault) | Approver | [Intuit](https://www.github.com/intuit/) |
| Christian Hernandez | [christianh814](https://github.com/christianh814) | Reviewer(docs) | [Akuity](https://akuity.io/) |
| Peter Jiang | [pjiang](https://github.com/pjiang) | Reviewer | [Intuit](https://www.intuit.com/) |
| Peter Jiang | [pjiang-dev](https://github.com/pjiang-dev) | Approver(docs) | [Intuit](https://www.intuit.com/) |
| Andrii Korotkov | [andrii-korotkov](https://github.com/andrii-korotkov) | Reviewer | [Verkada](https://www.verkada.com/) |
| Pasha Kostohrys | [pasha-codefresh](https://github.com/pasha-codefresh) | Approver | [Codefresh](https://www.github.com/codefresh/) |
| Nitish Kumar | [nitishfy](https://github.com/nitishfy) | Approver(cli,docs) | [Akuity](https://akuity.io/) |
| Justin Marquis | [34fathombelow](https://github.com/34fathombelow) | Approver(docs/ci) | [Akuity](https://akuity.io/) |
| Alexander Matyushentsev | [alexmt](https://github.com/alexmt) | Lead | [Akuity](https://akuity.io/) |
| Nicholas Morey | [morey-tech](https://github.com/morey-tech) | Reviewer(docs) | [Akuity](https://akuity.io/) |
| Papapetrou Patroklos | [ppapapetrou76](https://github.com/ppapapetrou76) | Reviewer | [Octopus Deploy](https://octopus.com/) |
| Papapetrou Patroklos | [ppapapetrou76](https://github.com/ppapapetrou76) | Approver(docs,cli) | [Octopus Deploy](https://octopus.com/) |
| Blake Pettersson | [blakepettersson](https://github.com/blakepettersson) | Approver | [Akuity](https://akuity.io/) |
| Ishita Sequeira | [ishitasequeira](https://github.com/ishitasequeira) | Approver | [Red Hat](https://redhat.com/) |
| Ashutosh Singh | [ashutosh16](https://github.com/ashutosh16) | Approver(docs) | [Intuit](https://www.github.com/intuit/) |
@@ -37,3 +37,7 @@ This document lists the maintainers of the Argo CD project.
| Regina Voloshin | [reggie-k](https://github.com/reggie-k) | Approver | [Octopus Deploy](https://octopus.com/) |
| Hong Wang | [wanghong230](https://github.com/wanghong230) | Reviewer | [Akuity](https://akuity.io/) |
| Jonathan West | [jgwest](https://github.com/jgwest) | Approver | [Red Hat](https://redhat.com/) |
| Jaewoo Choi | [choejwoo](https://github.com/choejwoo) | Reviewer | [Hyundai-Autoever](https://www.hyundai-autoever.com/eng/) |
| Alexy Mantha | [alexymantha](https://github.com/alexymantha) | Reviewer | GoTo |
| Kanika Rana | [ranakan19](https://github.com/ranakan19) | Reviewer | [Red Hat](https://redhat.com/) |
| Jonathan Winters | [jwinters01](https://github.com/jwinters01) | Reviewer | [Intuit](https://www.github.com/intuit/) |

View File

@@ -353,7 +353,7 @@ controller:
build-ui:
DOCKER_BUILDKIT=1 $(DOCKER) build -t argocd-ui --platform=$(TARGET_ARCH) --target argocd-ui .
find ./ui/dist -type f -not -name gitkeep -delete
$(DOCKER) run -v ${CURRENT_DIR}/ui/dist/app:/tmp/app --rm -t argocd-ui sh -c 'cp -r ./dist/app/* /tmp/app/'
$(DOCKER) run -u $(CONTAINER_UID):$(CONTAINER_GID) -v ${CURRENT_DIR}/ui/dist/app:/tmp/app --rm -t argocd-ui sh -c 'cp -r ./dist/app/* /tmp/app/'
.PHONY: image
ifeq ($(DEV_IMAGE), true)
@@ -444,17 +444,23 @@ test: test-tools-image
# Run all unit tests (local version)
.PHONY: test-local
test-local: test-gitops-engine
# run if TEST_MODULE is empty or does not point to gitops-engine tests
ifneq ($(if $(TEST_MODULE),,ALL)$(filter-out github.com/argoproj/argo-cd/gitops-engine% ./gitops-engine%,$(TEST_MODULE)),)
if test "$(TEST_MODULE)" = ""; then \
DIST_DIR=${DIST_DIR} RERUN_FAILS=0 PACKAGES=`go list ./... | grep -v 'test/e2e'` ./hack/test.sh -args -test.gocoverdir="$(PWD)/test-results"; \
else \
DIST_DIR=${DIST_DIR} RERUN_FAILS=0 PACKAGES="$(TEST_MODULE)" ./hack/test.sh -args -test.gocoverdir="$(PWD)/test-results" "$(TEST_MODULE)"; \
fi
endif
# Run gitops-engine unit tests
.PHONY: test-gitops-engine
test-gitops-engine:
# run if TEST_MODULE is empty or points to gitops-engine tests
ifneq ($(if $(TEST_MODULE),,ALL)$(filter github.com/argoproj/argo-cd/gitops-engine% ./gitops-engine%,$(TEST_MODULE)),)
mkdir -p $(PWD)/test-results
cd gitops-engine && go test -race -cover ./... -args -test.gocoverdir="$(PWD)/test-results"
endif
.PHONY: test-race
test-race: test-tools-image

View File

@@ -1,6 +1,6 @@
controller: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "GOCOVERDIR=${ARGOCD_COVERAGE_DIR:-/tmp/coverage/app-controller} HOSTNAME=testappcontroller-1 FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-application-controller $COMMAND --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081} --commit-server localhost:${ARGOCD_E2E_COMMITSERVER_PORT:-8086} --otlp-address=${ARGOCD_OTLP_ADDRESS} --application-namespaces=${ARGOCD_APPLICATION_NAMESPACES:-''} --server-side-diff-enabled=${ARGOCD_APPLICATION_CONTROLLER_SERVER_SIDE_DIFF:-'false'} --hydrator-enabled=${ARGOCD_HYDRATOR_ENABLED:='false'}"
api-server: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "GOCOVERDIR=${ARGOCD_COVERAGE_DIR:-/tmp/coverage/api-server} FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-server $COMMAND --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --disable-auth=${ARGOCD_E2E_DISABLE_AUTH:-'true'} --insecure --dex-server http://localhost:${ARGOCD_E2E_DEX_PORT:-5556} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081} --port ${ARGOCD_E2E_APISERVER_PORT:-8080} --otlp-address=${ARGOCD_OTLP_ADDRESS} --application-namespaces=${ARGOCD_APPLICATION_NAMESPACES:-''} --hydrator-enabled=${ARGOCD_HYDRATOR_ENABLED:='false'}"
dex: sh -c "ARGOCD_BINARY_NAME=argocd-dex go run github.com/argoproj/argo-cd/v3/cmd gendexcfg -o `pwd`/dist/dex.yaml && (test -f dist/dex.yaml || { echo 'Failed to generate dex configuration'; exit 1; }) && docker run --rm -p ${ARGOCD_E2E_DEX_PORT:-5556}:${ARGOCD_E2E_DEX_PORT:-5556} -v `pwd`/dist/dex.yaml:/dex.yaml ghcr.io/dexidp/dex:$(grep "image: ghcr.io/dexidp/dex" manifests/base/dex/argocd-dex-server-deployment.yaml | cut -d':' -f3) dex serve /dex.yaml"
dex: sh -c "ARGOCD_BINARY_NAME=argocd-dex go run github.com/argoproj/argo-cd/v3/cmd gendexcfg -o `pwd`/dist/dex.yaml && (test -f dist/dex.yaml || { echo 'Failed to generate dex configuration'; exit 1; }) && docker run --rm -p ${ARGOCD_E2E_DEX_PORT:-5556}:${ARGOCD_E2E_DEX_PORT:-5556} -v `pwd`/dist/dex.yaml:/dex.yaml ghcr.io/dexidp/dex:$(grep "image: ghcr.io/dexidp/dex:v2.45.0" manifests/base/dex/argocd-dex-server-deployment.yaml | cut -d':' -f3) dex serve /dex.yaml"
redis: hack/start-redis-with-password.sh
repo-server: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "export PATH=./dist:\$PATH && [ -n \"\$ARGOCD_GIT_CONFIG\" ] && export GIT_CONFIG_GLOBAL=\$ARGOCD_GIT_CONFIG && export GIT_CONFIG_NOSYSTEM=1; GOCOVERDIR=${ARGOCD_COVERAGE_DIR:-/tmp/coverage/repo-server} FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_GNUPGHOME=${ARGOCD_GNUPGHOME:-/tmp/argocd-local/gpg/keys} ARGOCD_PLUGINSOCKFILEPATH=${ARGOCD_PLUGINSOCKFILEPATH:-./test/cmp} ARGOCD_GPG_DATA_PATH=${ARGOCD_GPG_DATA_PATH:-/tmp/argocd-local/gpg/source} ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-repo-server ARGOCD_GPG_ENABLED=${ARGOCD_GPG_ENABLED:-false} $COMMAND --loglevel debug --port ${ARGOCD_E2E_REPOSERVER_PORT:-8081} --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --otlp-address=${ARGOCD_OTLP_ADDRESS}"
cmp-server: [ "$ARGOCD_E2E_TEST" = 'true' ] && exit 0 || [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_BINARY_NAME=argocd-cmp-server ARGOCD_PLUGINSOCKFILEPATH=${ARGOCD_PLUGINSOCKFILEPATH:-./test/cmp} $COMMAND --config-dir-path ./test/cmp --loglevel debug --otlp-address=${ARGOCD_OTLP_ADDRESS}"

View File

@@ -48,6 +48,23 @@ otherwise very intrusive, and there's a workaround available, we may decide to
provide a forward-fix only, e.g. to be released the next minor release, instead
of releasing it within a patch branch for the currently supported releases.
## Dependency Upgrade Policy
Argo CD relies on certain binaries and libraries that might appear in security scanners.
Upgrading certain dependencies, such as Helm, Kustomize, and git, may have negative impacts
on users, as they may include breaking changes or changes in behavior. For this reason,
we will only upgrade to new patch versions within the same minor version series within
a supported Argo CD version. For example, if we are currently on Helm 3.12.0 and Argo CD
3.4.0, we will only upgrade to Helm 3.12.x within Argo CD 3.4.x, and not to Helm 3.13.0
or later.
If there is a critical, _exploitable_ vulnerability in a dependency that will not be fixed
in a patch release, we will evaluate the impact of the vulnerability and the risk of not
upgrading the dependency. We ask that, if you believe a version bump is justified, please
open an issue _describing how the vulnerability is exploitable in the context of Argo CD_,
and we will evaluate it and decide whether or not to upgrade the dependency.
## Reporting a Vulnerability
If you find a security related bug in Argo CD, we kindly ask you for responsible

View File

@@ -1,6 +1,10 @@
load('ext://restart_process', 'docker_build_with_restart')
load('ext://uibutton', 'cmd_button', 'location')
# tilt version should be >= v0.37.0 for k8s_server_side_apply tilt-dev/tilt#6680
update_settings(
k8s_server_side_apply="true",
)
# add ui button in web ui to run make codegen-local (top nav)
cmd_button(
'make codegen-local',
@@ -52,6 +56,7 @@ local_resource(
'build',
'CGO_ENABLED=0 GOOS=linux GOARCH=' + arch + ' go build -gcflags="all=-N -l" -mod=readonly -o .tilt-bin/argocd_linux cmd/main.go',
deps = code_deps,
ignore = ['**/*_test.go'],
allow_parallel=True,
)
@@ -60,7 +65,7 @@ k8s_yaml(kustomize('manifests/dev-tilt'))
# build dev image
docker_build_with_restart(
'argocd',
'quay.io/argoproj/argocd:latest',
context='.',
dockerfile='Dockerfile.tilt',
entrypoint=[

View File

@@ -7,7 +7,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [100ms](https://www.100ms.ai/)
1. [127Labs](https://127labs.com/)
1. [3Rein](https://www.3rein.com/)
1. [3Rein](https://3reinmedia.com/)
1. [42 School](https://42.fr/)
1. [4data](https://4data.ch/)
1. [7shifts](https://www.7shifts.com/)
@@ -31,8 +31,8 @@ Currently, the following organizations are **officially** using Argo CD:
1. [ANSTO - Australian Synchrotron](https://www.synchrotron.org.au/)
1. [Ant Group](https://www.antgroup.com/)
1. [AppDirect](https://www.appdirect.com)
1. [Arcadia](https://www.arcadia.io)
1. [Arctiq Inc.](https://www.arctiq.ca)
1. [Arcadia](https://arcadia.io/)
1. [Arctiq Inc.](https://arctiq.com/)
1. [Artemis Health by Nomi Health](https://www.artemishealth.com/)
1. [Arturia](https://www.arturia.com)
1. [ARZ Allgemeines Rechenzentrum GmbH](https://www.arz.at/)
@@ -75,6 +75,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Chargetrip](https://chargetrip.com)
1. [Chime](https://www.chime.com)
1. [Chronicle Labs](https://chroniclelabs.org)
1. [C.H.Robinson ](https://www.chrobinson.com)
1. [Cisco ET&I](https://eti.cisco.com/)
1. [Close](https://www.close.com/)
1. [Cloud Posse](https://www.cloudposse.com/)
@@ -147,14 +148,14 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Getir](https://getir.com)
1. [GetYourGuide](https://www.getyourguide.com/)
1. [Gitpod](https://www.gitpod.io)
1. [Gllue](https://gllue.com)
1. [Gllue](https://www.gllue.com/)
1. [gloat](https://gloat.com/)
1. [GLOBIS](https://globis.com)
1. [Glovo](https://www.glovoapp.com)
1. [GlueOps](https://glueops.dev)
1. [GMETRI](https://gmetri.com/)
1. [Gojek](https://www.gojek.io/)
1. [GoTo Financial](https://gotofinancial.com/)
1. [GoTo Financial](https://www.gotocompany.com/en/products/goto-financial)
1. [GoTo](https://www.goto.com/)
1. [Greenpass](https://www.greenpass.com.br/)
1. [Gridfuse](https://gridfuse.com/)
@@ -165,7 +166,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Healy](https://www.healyworld.net)
1. [Helio](https://helio.exchange)
1. [hetao101](https://www.hetao101.com/)
1. [Hetki](https://hetki.ai)
1. [Hetki](https://hetki.io/)
1. [hipages](https://hipages.com.au/)
1. [Hiya](https://hiya.com)
1. [Honestbank](https://honestbank.com)
@@ -177,7 +178,8 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Icelandair](https://www.icelandair.com)
1. [IFS](https://www.ifs.com)
1. [IITS-Consulting](https://iits-consulting.de)
1. [IllumiDesk](https://www.illumidesk.com)
1. [IllumiDesk](https://illumichat.com/)
1. [Imagine Learning](https://www.imaginelearning.com/)
1. [imaware](https://imaware.health)
1. [Indeed](https://indeed.com)
1. [Index Exchange](https://www.indexexchange.com/)
@@ -212,7 +214,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [LeFigaro](https://www.lefigaro.fr/)
1. [Lely](https://www.lely.com/)
1. [LexisNexis](https://www.lexisnexis.com/)
1. [Lian Chu Securities](https://lczq.com)
1. [Lian Chu Securities](https://www.lczq.com/)
1. [Liatrio](https://www.liatrio.com)
1. [Lightricks](https://www.lightricks.com/)
1. [Loom](https://www.loom.com/)
@@ -245,7 +247,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [MTN Group](https://www.mtn.com/)
1. [Municipality of The Hague](https://www.denhaag.nl/)
1. [My Job Glasses](https://myjobglasses.com)
1. [Natura &Co](https://naturaeco.com/)
1. [Natura &Co](https://ri.natura.com.br/)
1. [Netease Cloud Music](https://music.163.com/)
1. [Nethopper](https://nethopper.io)
1. [New Relic](https://newrelic.com/)
@@ -276,7 +278,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Orbital Insight](https://orbitalinsight.com/)
1. [Oscar Health Insurance](https://hioscar.com/)
1. [Outpost24](https://outpost24.com/)
1. [p3r](https://www.p3r.one/)
1. [p3r](https://persona.atlus.com/p3r/)
1. [Packlink](https://www.packlink.com/)
1. [PagerDuty](https://www.pagerduty.com/)
1. [Pandosearch](https://www.pandosearch.com/en/home)
@@ -330,6 +332,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Salad Technologies](https://salad.com/)
1. [Saloodo! GmbH](https://www.saloodo.com)
1. [Sap Labs](http://sap.com)
1. [SAP Signavio](https://www.signavio.com)
1. [Sauce Labs](https://saucelabs.com/)
1. [Schneider Electric](https://www.se.com)
1. [Schwarz IT](https://jobs.schwarz/it-mission)
@@ -417,18 +420,18 @@ Currently, the following organizations are **officially** using Argo CD:
1. [VSHN - The DevOps Company](https://vshn.ch/)
1. [Wakacje.pl](https://www.wakacje.pl/)
1. [Walkbase](https://www.walkbase.com/)
1. [Webstores](https://www.webstores.nl)
1. [Webstores](https://www.friday.nl/)
1. [Wehkamp](https://www.wehkamp.nl/)
1. [WeMaintain](https://www.wemaintain.com/)
1. [WeMo Scooter](https://www.wemoscooter.com/)
1. [Whitehat Berlin](https://whitehat.berlin) by Guido Maria Serra +Fenaroli
1. [Witick](https://witick.io/)
1. [Witick](https://www.witik.io/en/)
1. [Wolffun Game](https://www.wolffungame.com/)
1. [WooliesX](https://wooliesx.com.au/)
1. [Woolworths Group](https://www.woolworthsgroup.com.au/)
1. [WSpot](https://www.wspot.com.br/)
1. [X3M ads](https://x3mads.com)
1. [Yieldlab](https://www.yieldlab.de/)
1. [Yieldlab](https://virtualminds.com/)
1. [Youverify](https://youverify.co/)
1. [Yubo](https://www.yubo.live/)
1. [Yuno](https://y.uno/)

View File

@@ -1 +1 @@
3.4.0
3.4.0-rc1

View File

@@ -20,6 +20,7 @@ import (
"fmt"
"reflect"
"runtime/debug"
"slices"
"sort"
"strconv"
"strings"
@@ -37,7 +38,6 @@ import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/record"
"k8s.io/client-go/util/retry"
"k8s.io/utils/ptr"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -47,7 +47,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"github.com/argoproj/gitops-engine/pkg/health"
"github.com/argoproj/argo-cd/gitops-engine/pkg/health"
"github.com/argoproj/argo-cd/v3/applicationset/controllers/template"
"github.com/argoproj/argo-cd/v3/applicationset/generators"
@@ -243,11 +243,6 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
return ctrl.Result{}, fmt.Errorf("failed to get current applications for application set: %w", err)
}
err = r.updateResourcesStatus(ctx, logCtx, &applicationSetInfo, currentApplications)
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to get update resources status for application set: %w", err)
}
// appSyncMap tracks which apps will be synced during this reconciliation.
appSyncMap := map[string]bool{}
@@ -371,6 +366,16 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
}
// Update resources status after create/update/delete so it reflects the actual cluster state.
currentApplications, err = r.getCurrentApplications(ctx, applicationSetInfo)
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to get current applications for application set: %w", err)
}
err = r.updateResourcesStatus(ctx, logCtx, &applicationSetInfo, currentApplications)
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to update resources status for application set: %w", err)
}
if applicationSetInfo.RefreshRequired() {
delete(applicationSetInfo.Annotations, common.AnnotationApplicationSetRefresh)
err := r.Update(ctx, &applicationSetInfo)
@@ -1046,12 +1051,10 @@ func labelMatchedExpression(logCtx *log.Entry, val string, matchExpression argov
// if operator == NotIn, default to true
valueMatched := matchExpression.Operator == "NotIn"
for _, value := range matchExpression.Values {
if val == value {
// first "In" match returns true
// first "NotIn" match returns false
return matchExpression.Operator == "In"
}
if slices.Contains(matchExpression.Values, val) {
// first "In" match returns true
// first "NotIn" match returns false
return matchExpression.Operator == "In"
}
return valueMatched
}
@@ -1583,8 +1586,8 @@ func (r *ApplicationSetReconciler) syncDesiredApplications(logCtx *log.Entry, ap
// ensure that Applications generated with RollingSync do not have an automated sync policy, since the AppSet controller will handle triggering the sync operation instead
if desiredApplications[i].Spec.SyncPolicy != nil && desiredApplications[i].Spec.SyncPolicy.IsAutomatedSyncEnabled() {
pruneEnabled = desiredApplications[i].Spec.SyncPolicy.Automated.Prune
desiredApplications[i].Spec.SyncPolicy.Automated.Enabled = ptr.To(false)
pruneEnabled = desiredApplications[i].Spec.SyncPolicy.Automated.GetPrune()
desiredApplications[i].Spec.SyncPolicy.Automated.Enabled = new(false)
}
appSetStatusPending := false

View File

@@ -28,8 +28,8 @@ import (
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/event"
"github.com/argoproj/gitops-engine/pkg/health"
"github.com/argoproj/gitops-engine/pkg/sync/common"
"github.com/argoproj/argo-cd/gitops-engine/pkg/health"
"github.com/argoproj/argo-cd/gitops-engine/pkg/sync/common"
"github.com/argoproj/argo-cd/v3/applicationset/generators"
"github.com/argoproj/argo-cd/v3/applicationset/generators/mocks"
@@ -2950,6 +2950,112 @@ func TestUpdatePerformedWithSyncPolicySync(t *testing.T) {
assert.Equal(t, map[string]string{"label-key": "label-value"}, app.Labels)
}
// TestReconcilePopulatesResourcesStatusOnFirstRun verifies that status.resources and status.resourcesCount
// are populated after the first reconcile, when applications are created.
func TestReconcilePopulatesResourcesStatusOnFirstRun(t *testing.T) {
scheme := runtime.NewScheme()
err := v1alpha1.AddToScheme(scheme)
require.NoError(t, err)
err = corev1.AddToScheme(scheme)
require.NoError(t, err)
defaultProject := v1alpha1.AppProject{
ObjectMeta: metav1.ObjectMeta{Name: "default", Namespace: "argocd"},
Spec: v1alpha1.AppProjectSpec{SourceRepos: []string{"*"}, Destinations: []v1alpha1.ApplicationDestination{{Namespace: "*", Server: "https://good-cluster"}}},
}
applicationsSyncPolicy := v1alpha1.ApplicationsSyncPolicySync
appSet := v1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "argocd",
},
Spec: v1alpha1.ApplicationSetSpec{
Generators: []v1alpha1.ApplicationSetGenerator{
{
List: &v1alpha1.ListGenerator{
Elements: []apiextensionsv1.JSON{{
Raw: []byte(`{"cluster": "good-cluster","url": "https://good-cluster"}`),
}},
},
},
},
SyncPolicy: &v1alpha1.ApplicationSetSyncPolicy{
ApplicationsSync: &applicationsSyncPolicy,
},
Template: v1alpha1.ApplicationSetTemplate{
ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{
Name: "{{cluster}}",
Namespace: "argocd",
},
Spec: v1alpha1.ApplicationSpec{
Source: &v1alpha1.ApplicationSource{RepoURL: "https://github.com/argoproj/argocd-example-apps", Path: "guestbook"},
Project: "default",
Destination: v1alpha1.ApplicationDestination{Server: "{{url}}"},
},
},
},
}
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "my-cluster",
Namespace: "argocd",
Labels: map[string]string{
argocommon.LabelKeySecretType: argocommon.LabelValueSecretTypeCluster,
},
},
Data: map[string][]byte{
"name": []byte("good-cluster"),
"server": []byte("https://good-cluster"),
"config": []byte("{\"username\":\"foo\",\"password\":\"foo\"}"),
},
}
kubeclientset := getDefaultTestClientSet(secret)
client := fake.NewClientBuilder().
WithScheme(scheme).
WithObjects(&appSet, &defaultProject, secret).
WithStatusSubresource(&appSet).
WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).
Build()
metrics := appsetmetrics.NewFakeAppsetMetrics()
argodb := db.NewDB("argocd", settings.NewSettingsManager(t.Context(), kubeclientset, "argocd"), kubeclientset)
clusterInformer, err := settings.NewClusterInformer(kubeclientset, "argocd")
require.NoError(t, err)
defer startAndSyncInformer(t, clusterInformer)()
r := ApplicationSetReconciler{
Client: client,
Scheme: scheme,
Renderer: &utils.Render{},
Recorder: record.NewFakeRecorder(1),
Generators: map[string]generators.Generator{"List": generators.NewListGenerator()},
ArgoDB: argodb,
ArgoCDNamespace: "argocd",
KubeClientset: kubeclientset,
Policy: v1alpha1.ApplicationsSyncPolicySync,
Metrics: metrics,
ClusterInformer: clusterInformer,
}
req := ctrl.Request{
NamespacedName: types.NamespacedName{Namespace: "argocd", Name: "name"},
}
_, err = r.Reconcile(t.Context(), req)
require.NoError(t, err)
var retrievedAppSet v1alpha1.ApplicationSet
err = r.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "name"}, &retrievedAppSet)
require.NoError(t, err)
assert.Len(t, retrievedAppSet.Status.Resources, 1, "status.resources should have 1 item after first reconcile")
assert.Equal(t, int64(1), retrievedAppSet.Status.ResourcesCount, "status.resourcesCount should be 1 after first reconcile")
assert.Equal(t, "good-cluster", retrievedAppSet.Status.Resources[0].Name)
}
func TestUpdatePerformedWithSyncPolicyCreateOnlyAndAllowPolicyOverrideFalse(t *testing.T) {
applicationsSyncPolicy := v1alpha1.ApplicationsSyncPolicyCreateOnly
@@ -4652,7 +4758,7 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
newDefaultAppSet := func(stepsCount int, status []v1alpha1.ApplicationSetApplicationStatus) v1alpha1.ApplicationSet {
steps := []v1alpha1.ApplicationSetRolloutStep{}
for i := 0; i < stepsCount; i++ {
for range stepsCount {
steps = append(steps, v1alpha1.ApplicationSetRolloutStep{MatchExpressions: []v1alpha1.ApplicationMatchExpression{}})
}
return v1alpha1.ApplicationSet{
@@ -6365,7 +6471,7 @@ func TestUpdateResourceStatus(t *testing.T) {
func generateNAppResourceStatuses(n int) []v1alpha1.ResourceStatus {
var r []v1alpha1.ResourceStatus
for i := 0; i < n; i++ {
for i := range n {
r = append(r, v1alpha1.ResourceStatus{
Name: "app" + strconv.Itoa(i),
Status: v1alpha1.SyncStatusCodeSynced,
@@ -6380,7 +6486,7 @@ func generateNAppResourceStatuses(n int) []v1alpha1.ResourceStatus {
func generateNHealthyApps(n int) []v1alpha1.Application {
var r []v1alpha1.Application
for i := 0; i < n; i++ {
for i := range n {
r = append(r, v1alpha1.Application{
ObjectMeta: metav1.ObjectMeta{
Name: "app" + strconv.Itoa(i),

View File

@@ -96,7 +96,7 @@ func Test_ApplyTemplatePatch(t *testing.T) {
},
SyncPolicy: &appv1.SyncPolicy{
Automated: &appv1.SyncPolicyAutomated{
Prune: true,
Prune: new(true),
},
},
},
@@ -172,7 +172,7 @@ spec:
},
SyncPolicy: &appv1.SyncPolicy{
Automated: &appv1.SyncPolicyAutomated{
Prune: true,
Prune: new(true),
},
},
},

View File

@@ -124,7 +124,7 @@ func GetRelevantGenerators(requestedGenerator *argoprojiov1alpha1.ApplicationSet
}
func flattenParameters(in map[string]any) (map[string]string, error) {
flat, err := flatten.Flatten(in, "", flatten.DotStyle)
flat, err := flatten.Flatten(normalizeMapForFlatten(in), "", flatten.DotStyle)
if err != nil {
return nil, fmt.Errorf("error flatenning parameters: %w", err)
}
@@ -137,6 +137,31 @@ func flattenParameters(in map[string]any) (map[string]string, error) {
return out, nil
}
// normalizeMapForFlatten recursively converts map[string]string values to
// map[string]interface{} so that flatten.Flatten can recurse into them.
// flatten.Flatten only recurses into map[string]interface{} and []interface{};
// map[string]string is treated as an opaque leaf, causing individual keys
// (e.g. metadata.labels.environment) to be absent from the flat output and
// silently breaking post-generator selector matching in GoTemplate mode.
func normalizeMapForFlatten(in map[string]any) map[string]any {
out := make(map[string]any, len(in))
for k, v := range in {
switch cast := v.(type) {
case map[string]string:
inner := make(map[string]any, len(cast))
for ik, iv := range cast {
inner[ik] = iv
}
out[k] = inner
case map[string]any:
out[k] = normalizeMapForFlatten(cast)
default:
out[k] = v
}
}
return out
}
func mergeGeneratorTemplate(g Generator, requestedGenerator *argoprojiov1alpha1.ApplicationSetGenerator, applicationSetTemplate argoprojiov1alpha1.ApplicationSetTemplate) (argoprojiov1alpha1.ApplicationSetTemplate, error) {
// Make a copy of the value from `GetTemplate()` before merge, rather than copying directly into
// the provided parameter (which will touch the original resource object returned by client-go)

View File

@@ -249,6 +249,231 @@ func TestTransForm(t *testing.T) {
}
}
func TestTransFormGoTemplate(t *testing.T) {
testCases := []struct {
name string
selector *metav1.LabelSelector
values map[string]string
expected []map[string]any
}{
{
name: "server filter",
selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"server": "https://production-01.example.com"},
},
expected: []map[string]any{{
"name": "production_01/west",
"nameNormalized": "production-01-west",
"server": "https://production-01.example.com",
"project": "",
"metadata": map[string]any{
"labels": map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "production",
"org": "bar",
},
"annotations": map[string]string{
"foo.argoproj.io": "production",
},
},
}},
},
{
name: "label MatchLabels",
selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"metadata.labels.environment": "staging"},
},
expected: []map[string]any{{
"name": "staging-01",
"nameNormalized": "staging-01",
"server": "https://staging-01.example.com",
"project": "",
"metadata": map[string]any{
"labels": map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "staging",
"org": "foo",
},
"annotations": map[string]string{
"foo.argoproj.io": "staging",
},
},
}},
},
{
name: "label NotIn matchExpression",
selector: &metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "metadata.labels.environment",
Operator: metav1.LabelSelectorOpNotIn,
Values: []string{"staging"},
},
},
},
// staging-01 is excluded; production-01, some-really-long-server-url, and
// in-cluster (no labels) are all included because NotIn vacuously passes
// when the key is absent.
expected: []map[string]any{
{
"name": "production_01/west",
"nameNormalized": "production-01-west",
"server": "https://production-01.example.com",
"project": "",
"metadata": map[string]any{
"labels": map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "production",
"org": "bar",
},
"annotations": map[string]string{
"foo.argoproj.io": "production",
},
},
},
{
"name": "some-really-long-server-url",
"nameNormalized": "some-really-long-server-url",
"server": "https://some-really-long-url-that-will-exceed-63-characters.com",
"project": "",
"metadata": map[string]any{
"labels": map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "production",
"org": "bar",
},
"annotations": map[string]string{
"foo.argoproj.io": "production",
},
},
},
{
// in-cluster (local cluster) has no labels; NotIn vacuously passes.
"name": "in-cluster",
"nameNormalized": "in-cluster",
"server": "https://kubernetes.default.svc",
"project": "",
},
},
},
{
name: "slash key in label",
selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"metadata.labels.argocd.argoproj.io/secret-type": "cluster"},
},
expected: []map[string]any{
{
"name": "staging-01",
"nameNormalized": "staging-01",
"server": "https://staging-01.example.com",
"project": "",
"metadata": map[string]any{
"labels": map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "staging",
"org": "foo",
},
"annotations": map[string]string{
"foo.argoproj.io": "staging",
},
},
},
{
"name": "production_01/west",
"nameNormalized": "production-01-west",
"server": "https://production-01.example.com",
"project": "",
"metadata": map[string]any{
"labels": map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "production",
"org": "bar",
},
"annotations": map[string]string{
"foo.argoproj.io": "production",
},
},
},
{
"name": "some-really-long-server-url",
"nameNormalized": "some-really-long-server-url",
"server": "https://some-really-long-url-that-will-exceed-63-characters.com",
"project": "",
"metadata": map[string]any{
"labels": map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "production",
"org": "bar",
},
"annotations": map[string]string{
"foo.argoproj.io": "production",
},
},
},
},
},
{
name: "values filter",
selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"values.env": "staging"},
},
values: map[string]string{"env": "{{.metadata.labels.environment}}"},
expected: []map[string]any{{
"name": "staging-01",
"nameNormalized": "staging-01",
"server": "https://staging-01.example.com",
"project": "",
"metadata": map[string]any{
"labels": map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "staging",
"org": "foo",
},
"annotations": map[string]string{
"foo.argoproj.io": "staging",
},
},
"values": map[string]string{
"env": "staging",
},
}},
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
testGenerators := map[string]Generator{
"Clusters": getMockClusterGenerator(),
}
applicationSetInfo := argov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "set",
},
Spec: argov1alpha1.ApplicationSetSpec{
GoTemplate: true,
},
}
results, err := Transform(
argov1alpha1.ApplicationSetGenerator{
Selector: testCase.selector,
Clusters: &argov1alpha1.ClusterGenerator{
Selector: metav1.LabelSelector{},
Template: argov1alpha1.ApplicationSetTemplate{},
Values: testCase.values,
},
},
testGenerators,
emptyTemplate(),
&applicationSetInfo, nil, nil)
require.NoError(t, err)
assert.ElementsMatch(t, testCase.expected, results[0].Params)
})
}
}
func emptyTemplate() argov1alpha1.ApplicationSetTemplate {
return argov1alpha1.ApplicationSetTemplate{
Spec: argov1alpha1.ApplicationSpec{
@@ -528,7 +753,7 @@ func TestInterpolateGeneratorError(t *testing.T) {
{name: "Error templating", args: args{
requestedGenerator: &argov1alpha1.ApplicationSetGenerator{Git: &argov1alpha1.GitGenerator{
RepoURL: "foo",
Files: []argov1alpha1.GitFileGeneratorItem{{Path: "bar/"}},
Files: []argov1alpha1.GitFileGeneratorItem{{Path: "path/{{ index .rmap (default .override .test) }}"}},
Revision: "main",
Values: map[string]string{
"git_test": "{{ toPrettyJson . }}",
@@ -542,7 +767,7 @@ func TestInterpolateGeneratorError(t *testing.T) {
},
useGoTemplate: true,
goTemplateOptions: []string{},
}, want: argov1alpha1.ApplicationSetGenerator{}, expectedErrStr: "failed to replace parameters in generator: failed to execute go template {{ index .rmap (default .override .test) }}: template: base:1:3: executing \"base\" at <index .rmap (default .override .test)>: error calling index: index of untyped nil"},
}, want: argov1alpha1.ApplicationSetGenerator{}, expectedErrStr: "failed to replace parameters in generator: failed to execute go template path/{{ index .rmap (default .override .test) }}: template: base:1:8: executing \"base\" at <index .rmap (default .override .test)>: error calling index: index of untyped nil"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -556,3 +781,178 @@ func TestInterpolateGeneratorError(t *testing.T) {
})
}
}
func TestInterpolateGeneratorValuesHandling(t *testing.T) {
applicationSetTemplate := argov1alpha1.ApplicationSetTemplate{
ApplicationSetTemplateMeta: argov1alpha1.ApplicationSetTemplateMeta{
Labels: map[string]string{},
Annotations: map[string]string{},
Finalizers: []string{},
},
Spec: argov1alpha1.ApplicationSpec{
IgnoreDifferences: argov1alpha1.IgnoreDifferences{},
Info: []argov1alpha1.Info{},
Sources: argov1alpha1.ApplicationSources{},
},
}
type args struct {
requestedGenerator *argov1alpha1.ApplicationSetGenerator
params map[string]any
useGoTemplate bool
goTemplateOptions []string
}
tests := []struct {
name string
args args
want argov1alpha1.ApplicationSetGenerator
expectedErrStr string
}{
{
name: "Generator with values set",
args: args{
requestedGenerator: &argov1alpha1.ApplicationSetGenerator{
Git: &argov1alpha1.GitGenerator{
RepoURL: "https://somewhere.com/per-cluster/{{.name}}.git",
Files: []argov1alpha1.GitFileGeneratorItem{{Path: "somedir/*"}},
Revision: "main",
Values: map[string]string{
"appname": "{{ .path.basenameNormalized }}",
},
Template: applicationSetTemplate,
},
},
params: map[string]any{
"name": "in-cluster",
"server": "https://kubernetes.default.svc",
},
useGoTemplate: true,
goTemplateOptions: []string{},
},
want: argov1alpha1.ApplicationSetGenerator{
Git: &argov1alpha1.GitGenerator{
RepoURL: "https://somewhere.com/per-cluster/in-cluster.git",
Files: []argov1alpha1.GitFileGeneratorItem{{Path: "somedir/*"}},
Revision: "main",
Values: map[string]string{
// must stay not interpolated
"appname": "{{ .path.basenameNormalized }}",
},
Directories: []argov1alpha1.GitDirectoryGeneratorItem{},
Template: applicationSetTemplate,
},
},
expectedErrStr: "",
},
{
name: "Generator with no values set",
args: args{
requestedGenerator: &argov1alpha1.ApplicationSetGenerator{
Git: &argov1alpha1.GitGenerator{
RepoURL: "https://somewhere.com/per-cluster/{{.name}}.git",
Files: []argov1alpha1.GitFileGeneratorItem{{Path: "somedir/*"}},
Revision: "main",
Values: map[string]string{},
Template: applicationSetTemplate,
},
},
params: map[string]any{
"name": "in-cluster",
"server": "https://kubernetes.default.svc",
},
useGoTemplate: true,
goTemplateOptions: []string{},
},
want: argov1alpha1.ApplicationSetGenerator{
Git: &argov1alpha1.GitGenerator{
RepoURL: "https://somewhere.com/per-cluster/in-cluster.git",
Files: []argov1alpha1.GitFileGeneratorItem{{Path: "somedir/*"}},
Revision: "main",
Values: map[string]string{},
Directories: []argov1alpha1.GitDirectoryGeneratorItem{},
Template: applicationSetTemplate,
},
},
expectedErrStr: "",
},
{
name: "Generator with values set without go templates",
args: args{
requestedGenerator: &argov1alpha1.ApplicationSetGenerator{
Git: &argov1alpha1.GitGenerator{
RepoURL: "https://somewhere.com/per-cluster/{{name}}.git",
Files: []argov1alpha1.GitFileGeneratorItem{{Path: "somedir/*"}},
Revision: "main",
Values: map[string]string{
"appname": "{{ .path.basenameNormalized }}",
},
Template: applicationSetTemplate,
},
},
params: map[string]any{
"name": "in-cluster",
"server": "https://kubernetes.default.svc",
},
useGoTemplate: false,
},
want: argov1alpha1.ApplicationSetGenerator{
Git: &argov1alpha1.GitGenerator{
RepoURL: "https://somewhere.com/per-cluster/in-cluster.git",
Files: []argov1alpha1.GitFileGeneratorItem{{Path: "somedir/*"}},
Revision: "main",
Values: map[string]string{
"appname": "{{ .path.basenameNormalized }}",
},
Directories: []argov1alpha1.GitDirectoryGeneratorItem{},
Template: applicationSetTemplate,
},
},
expectedErrStr: "",
},
{
name: "Generator without values set and no go templates",
args: args{
requestedGenerator: &argov1alpha1.ApplicationSetGenerator{
Git: &argov1alpha1.GitGenerator{
RepoURL: "https://somewhere.com/per-cluster/{{name}}.git",
Files: []argov1alpha1.GitFileGeneratorItem{{Path: "somedir/*"}},
Revision: "main",
Values: map[string]string{},
Template: applicationSetTemplate,
},
},
params: map[string]any{
"name": "in-cluster",
"server": "https://kubernetes.default.svc",
},
useGoTemplate: false,
},
want: argov1alpha1.ApplicationSetGenerator{
Git: &argov1alpha1.GitGenerator{
RepoURL: "https://somewhere.com/per-cluster/in-cluster.git",
Files: []argov1alpha1.GitFileGeneratorItem{{Path: "somedir/*"}},
Revision: "main",
Values: map[string]string{},
Directories: []argov1alpha1.GitDirectoryGeneratorItem{},
Template: applicationSetTemplate,
},
},
expectedErrStr: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := InterpolateGenerator(tt.args.requestedGenerator, tt.args.params, tt.args.useGoTemplate, tt.args.goTemplateOptions)
if tt.expectedErrStr != "" {
require.EqualError(t, err, tt.expectedErrStr)
} else {
require.NoError(t, err)
}
assert.Equal(t, tt.want.Git.Values, got.Git.Values)
assert.Equal(t, tt.want.Git.Revision, got.Git.Revision)
assert.Equal(t, tt.want.Git.RepoURL, got.Git.RepoURL)
assert.Equal(t, tt.want.Git.Files, got.Git.Files)
assert.Equal(t, tt.want.Git.Directories, got.Git.Directories)
assert.Equal(t, tt.want.Git.Template, got.Git.Template)
})
}
}

View File

@@ -3,6 +3,7 @@ package generators
import (
"context"
"fmt"
"maps"
"path"
"sort"
"strconv"
@@ -168,9 +169,7 @@ func (g *GitGenerator) generateParamsForGitFiles(appSetGenerator *argoprojiov1al
if err != nil {
return nil, err
}
for absPath, content := range retrievedFiles {
fileContentMap[absPath] = content
}
maps.Copy(fileContentMap, retrievedFiles)
}
// Now remove files matching any exclude pattern
@@ -242,9 +241,7 @@ func (g *GitGenerator) generateParamsFromGitFile(filePath string, fileContent []
params := map[string]any{}
if useGoTemplate {
for k, v := range objectFound {
params[k] = v
}
maps.Copy(params, objectFound)
paramPath := map[string]any{}

View File

@@ -9,7 +9,6 @@ import (
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"github.com/argoproj/argo-cd/v3/applicationset/services/mocks"
@@ -111,13 +110,18 @@ foo:
{
name: "file parameters are added to params with go template",
args: args{
filePath: "path/dir/file_name.yaml",
fileContent: defaultContent,
values: map[string]string{},
filePath: "path/dir/file_name.yaml",
fileContent: defaultContent,
values: map[string]string{
"somekey": "{{.path.basename}}",
},
useGoTemplate: true,
},
want: []map[string]any{
{
"values": map[string]string{
"somekey": "dir",
},
"foo": map[string]any{
"bar": "baz",
},
@@ -165,6 +169,41 @@ foo:
},
},
},
{
name: "path parameter are prefixed with go template and values",
args: args{
filePath: "path/dir/file_name.yaml",
fileContent: defaultContent,
values: map[string]string{
"somekey": "{{.myRepo.path.basename}}",
},
useGoTemplate: true,
pathParamPrefix: "myRepo",
},
want: []map[string]any{
{
"foo": map[string]any{
"bar": "baz",
},
"myRepo": map[string]any{
"path": map[string]any{
"path": "path/dir",
"basename": "dir",
"filename": "file_name.yaml",
"basenameNormalized": "dir",
"filenameNormalized": "file-name.yaml",
"segments": []string{
"path",
"dir",
},
},
},
"values": map[string]string{
"somekey": "dir",
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -2423,7 +2462,7 @@ func TestGitGenerator_GenerateParams(t *testing.T) {
},
},
expected: []map[string]any{{"path": "app1", "path.basename": "app1", "path.basenameNormalized": "app1", "path[0]": "app1", "values.foo": "bar"}},
expectedProject: ptr.To("project"),
expectedProject: new("project"),
expectedError: nil,
},
{
@@ -2457,7 +2496,7 @@ func TestGitGenerator_GenerateParams(t *testing.T) {
},
},
expected: []map[string]any{{"path": "app1", "path.basename": "app1", "path.basenameNormalized": "app1", "path[0]": "app1", "values.foo": "bar"}},
expectedProject: ptr.To(""),
expectedProject: new(""),
expectedError: nil,
},
}

View File

@@ -1100,3 +1100,85 @@ func TestGitGenerator_GenerateParams_list_x_git_matrix_generator(t *testing.T) {
"test": "content",
}}, params)
}
func TestGitGenerator_GenerateParams_list_x_git_matrix_generator_go_templates_values(t *testing.T) {
// Given a matrix generator over a list generator and a git generator with values,
// that contain a template that refers to got generator output parameters.
// This tests for a specific bug where the second generator in the matrix
// failed to evaluate value templates that referred to generator output parameters.
listGeneratorMock := &generatorsMock.Generator{}
listGeneratorMock.EXPECT().GenerateParams(mock.AnythingOfType("*v1alpha1.ApplicationSetGenerator"), mock.AnythingOfType("*v1alpha1.ApplicationSet"), mock.Anything).Return([]map[string]any{
{"some": "value"},
}, nil)
listGeneratorMock.EXPECT().GetTemplate(mock.AnythingOfType("*v1alpha1.ApplicationSetGenerator")).Return(&v1alpha1.ApplicationSetTemplate{})
gitGeneratorSpec := &v1alpha1.GitGenerator{
RepoURL: "https://git.example.com",
Files: []v1alpha1.GitFileGeneratorItem{
{Path: "some/path.json"},
},
Values: map[string]string{
"foo": "{{.path.basename}}",
},
}
repoServiceMock := &servicesMocks.Repos{}
repoServiceMock.EXPECT().GetFiles(mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(map[string][]byte{
"some/path.json": []byte("test: content"),
}, nil).Maybe()
gitGenerator := NewGitGenerator(repoServiceMock, "")
matrixGenerator := NewMatrixGenerator(map[string]Generator{
"List": listGeneratorMock,
"Git": gitGenerator,
})
matrixGeneratorSpec := &v1alpha1.MatrixGenerator{
Generators: []v1alpha1.ApplicationSetNestedGenerator{
{
List: &v1alpha1.ListGenerator{
Elements: []apiextensionsv1.JSON{
{
Raw: []byte(`{"some": "value"}`),
},
},
},
},
{
Git: gitGeneratorSpec,
},
},
}
scheme := runtime.NewScheme()
err := v1alpha1.AddToScheme(scheme)
require.NoError(t, err)
appProject := v1alpha1.AppProject{}
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appProject).Build()
params, err := matrixGenerator.GenerateParams(&v1alpha1.ApplicationSetGenerator{
Matrix: matrixGeneratorSpec,
}, &v1alpha1.ApplicationSet{
Spec: v1alpha1.ApplicationSetSpec{
GoTemplate: true,
},
}, client)
require.NoError(t, err)
assert.Equal(t, []map[string]any{{
"path": map[string]any{
"basename": "some",
"basenameNormalized": "some",
"filename": "path.json",
"filenameNormalized": "path.json",
"path": "some",
"segments": []string{"some"},
},
"some": "value",
"test": "content",
"values": map[string]string{
"foo": "some",
},
}}, params)
}

View File

@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"maps"
"strconv"
"strings"
"time"
@@ -115,9 +116,7 @@ func (g *PluginGenerator) generateParams(appSetGenerator *argoprojiov1alpha1.App
params := map[string]any{}
if useGoTemplate {
for k, v := range objectFound {
params[k] = v
}
maps.Copy(params, objectFound)
} else {
flat, err := flatten.Flatten(objectFound, "", flatten.DotStyle)
if err != nil {

View File

@@ -96,15 +96,9 @@ func (g *PullRequestGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
var shortSHALength int
var shortSHALength7 int
for _, pull := range pulls {
shortSHALength = 8
if len(pull.HeadSHA) < 8 {
shortSHALength = len(pull.HeadSHA)
}
shortSHALength = min(len(pull.HeadSHA), 8)
shortSHALength7 = 7
if len(pull.HeadSHA) < 7 {
shortSHALength7 = len(pull.HeadSHA)
}
shortSHALength7 = min(len(pull.HeadSHA), 7)
paramMap := map[string]any{
"number": strconv.FormatInt(pull.Number, 10),

View File

@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"net/http"
"slices"
"strings"
"time"
@@ -105,10 +106,8 @@ func ScmProviderAllowed(applicationSetInfo *argoprojiov1alpha1.ApplicationSet, g
return nil
}
for _, allowedScmProvider := range allowedScmProviders {
if url == allowedScmProvider {
return nil
}
if slices.Contains(allowedScmProviders, url) {
return nil
}
log.WithFields(log.Fields{
@@ -244,15 +243,9 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
var shortSHALength int
var shortSHALength7 int
for _, repo := range repos {
shortSHALength = 8
if len(repo.SHA) < 8 {
shortSHALength = len(repo.SHA)
}
shortSHALength = min(len(repo.SHA), 8)
shortSHALength7 = 7
if len(repo.SHA) < 7 {
shortSHALength7 = len(repo.SHA)
}
shortSHALength7 = min(len(repo.SHA), 7)
params := map[string]any{
"organization": repo.Organization,

View File

@@ -2,6 +2,7 @@ package generators
import (
"fmt"
"maps"
)
func appendTemplatedValues(values map[string]string, params map[string]any, useGoTemplate bool, goTemplateOptions []string) error {
@@ -26,9 +27,7 @@ func appendTemplatedValues(values map[string]string, params map[string]any, useG
}
}
for key, value := range tmp {
params[key] = value
}
maps.Copy(params, tmp)
return nil
}

View File

@@ -151,9 +151,9 @@ spec:
func newFakeAppsets(fakeAppsetYAML string) []argoappv1.ApplicationSet {
var results []argoappv1.ApplicationSet
appsetRawYamls := strings.Split(fakeAppsetYAML, "---")
appsetRawYamls := strings.SplitSeq(fakeAppsetYAML, "---")
for _, appsetRawYaml := range appsetRawYamls {
for appsetRawYaml := range appsetRawYamls {
var appset argoappv1.ApplicationSet
err := yaml.Unmarshal([]byte(appsetRawYaml), &appset)
if err != nil {

View File

@@ -3,6 +3,7 @@ package pull_request
import (
"context"
"fmt"
"slices"
"strings"
"github.com/microsoft/azure-devops-go-api/azuredevops/v7"
@@ -136,13 +137,7 @@ func convertLabels(tags *[]core.WebApiTagDefinition) []string {
// containAzureDevOpsLabels returns true if gotLabels contains expectedLabels
func containAzureDevOpsLabels(expectedLabels []string, gotLabels []string) bool {
for _, expected := range expectedLabels {
found := false
for _, got := range gotLabels {
if expected == got {
found = true
break
}
}
found := slices.Contains(gotLabels, expected)
if !found {
return false
}

View File

@@ -15,26 +15,6 @@ import (
"github.com/argoproj/argo-cd/v3/applicationset/services/scm_provider/mocks"
)
func createBoolPtr(x bool) *bool {
return &x
}
func createStringPtr(x string) *string {
return &x
}
func createIntPtr(x int) *int {
return &x
}
func createLabelsPtr(x []core.WebApiTagDefinition) *[]core.WebApiTagDefinition {
return &x
}
func createUniqueNamePtr(x string) *string {
return &x
}
func TestListPullRequest(t *testing.T) {
teamProject := "myorg_project"
repoName := "myorg_project_repo"
@@ -46,19 +26,19 @@ func TestListPullRequest(t *testing.T) {
pullRequestMock := []git.GitPullRequest{
{
PullRequestId: createIntPtr(prID),
Title: createStringPtr(prTitle),
SourceRefName: createStringPtr("refs/heads/feature-branch"),
TargetRefName: createStringPtr("refs/heads/main"),
PullRequestId: new(prID),
Title: new(prTitle),
SourceRefName: new("refs/heads/feature-branch"),
TargetRefName: new("refs/heads/main"),
LastMergeSourceCommit: &git.GitCommitRef{
CommitId: createStringPtr(prHeadSha),
CommitId: new(prHeadSha),
},
Labels: &[]core.WebApiTagDefinition{},
Repository: &git.GitRepository{
Name: createStringPtr(repoName),
Name: new(repoName),
},
CreatedBy: &webapi.IdentityRef{
UniqueName: createUniqueNamePtr(uniqueName + "@example.com"),
UniqueName: new(uniqueName + "@example.com"),
},
},
}
@@ -99,27 +79,27 @@ func TestConvertLabes(t *testing.T) {
}{
{
name: "empty labels",
gotLabels: createLabelsPtr([]core.WebApiTagDefinition{}),
gotLabels: &[]core.WebApiTagDefinition{},
expectedLabels: []string{},
},
{
name: "nil labels",
gotLabels: createLabelsPtr(nil),
gotLabels: nil,
expectedLabels: []string{},
},
{
name: "one label",
gotLabels: createLabelsPtr([]core.WebApiTagDefinition{
{Name: createStringPtr("label1"), Active: createBoolPtr(true)},
}),
gotLabels: &[]core.WebApiTagDefinition{
{Name: new("label1"), Active: new(true)},
},
expectedLabels: []string{"label1"},
},
{
name: "two label",
gotLabels: createLabelsPtr([]core.WebApiTagDefinition{
{Name: createStringPtr("label1"), Active: createBoolPtr(true)},
{Name: createStringPtr("label2"), Active: createBoolPtr(true)},
}),
gotLabels: &[]core.WebApiTagDefinition{
{Name: new("label1"), Active: new(true)},
{Name: new("label2"), Active: new(true)},
},
expectedLabels: []string{"label1", "label2"},
},
}
@@ -216,7 +196,7 @@ func TestBuildURL(t *testing.T) {
func TestAzureDevOpsListReturnsRepositoryNotFoundError(t *testing.T) {
args := git.GetPullRequestsByProjectArgs{
Project: createStringPtr("nonexistent"),
Project: new("nonexistent"),
SearchCriteria: &git.GitPullRequestSearchCriteria{},
}

View File

@@ -268,7 +268,6 @@ func TestListPullRequestTLS(t *testing.T) {
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defaultHandler(t)(w, r)

View File

@@ -83,7 +83,7 @@ func (g *GiteaService) List(ctx context.Context) ([]*PullRequest, error) {
// containLabels returns true if gotLabels contains expectedLabels
func giteaContainLabels(expectedLabels []string, gotLabels []*gitea.Label) bool {
gotLabelNamesMap := make(map[string]bool)
for i := 0; i < len(gotLabels); i++ {
for i := range gotLabels {
gotLabelNamesMap[gotLabels[i].Name] = true
}
for _, expected := range expectedLabels {

View File

@@ -10,10 +10,6 @@ import (
"github.com/stretchr/testify/require"
)
func toPtr(s string) *string {
return &s
}
func TestContainLabels(t *testing.T) {
cases := []struct {
Name string
@@ -25,9 +21,9 @@ func TestContainLabels(t *testing.T) {
Name: "Match labels",
Labels: []string{"label1", "label2"},
PullLabels: []*github.Label{
{Name: toPtr("label1")},
{Name: toPtr("label2")},
{Name: toPtr("label3")},
{Name: new("label1")},
{Name: new("label2")},
{Name: new("label3")},
},
Expect: true,
},
@@ -35,9 +31,9 @@ func TestContainLabels(t *testing.T) {
Name: "Not match labels",
Labels: []string{"label1", "label4"},
PullLabels: []*github.Label{
{Name: toPtr("label1")},
{Name: toPtr("label2")},
{Name: toPtr("label3")},
{Name: new("label1")},
{Name: new("label2")},
{Name: new("label3")},
},
Expect: false,
},
@@ -45,9 +41,9 @@ func TestContainLabels(t *testing.T) {
Name: "No specify",
Labels: []string{},
PullLabels: []*github.Label{
{Name: toPtr("label1")},
{Name: toPtr("label2")},
{Name: toPtr("label3")},
{Name: new("label1")},
{Name: new("label2")},
{Name: new("label3")},
},
Expect: true,
},
@@ -70,9 +66,9 @@ func TestGetGitHubPRLabelNames(t *testing.T) {
{
Name: "PR has labels",
PullLabels: []*github.Label{
{Name: toPtr("label1")},
{Name: toPtr("label2")},
{Name: toPtr("label3")},
{Name: new("label1")},
{Name: new("label2")},
{Name: new("label3")},
},
ExpectedResult: []string{"label1", "label2", "label3"},
},

View File

@@ -158,7 +158,6 @@ func TestListWithStateTLS(t *testing.T) {
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
writeMRListResponse(t, w)

View File

@@ -9,10 +9,6 @@ import (
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
)
func strp(s string) *string {
return &s
}
func TestFilterBranchMatchBadRegexp(t *testing.T) {
provider, _ := NewFakeService(
t.Context(),
@@ -30,7 +26,7 @@ func TestFilterBranchMatchBadRegexp(t *testing.T) {
)
filters := []argoprojiov1alpha1.PullRequestGeneratorFilter{
{
BranchMatch: strp("("),
BranchMatch: new("("),
},
}
_, err := ListPullRequests(t.Context(), provider, filters)
@@ -78,7 +74,7 @@ func TestFilterBranchMatch(t *testing.T) {
)
filters := []argoprojiov1alpha1.PullRequestGeneratorFilter{
{
BranchMatch: strp("w"),
BranchMatch: new("w"),
},
}
pullRequests, err := ListPullRequests(t.Context(), provider, filters)
@@ -128,7 +124,7 @@ func TestFilterTargetBranchMatch(t *testing.T) {
)
filters := []argoprojiov1alpha1.PullRequestGeneratorFilter{
{
TargetBranchMatch: strp("1"),
TargetBranchMatch: new("1"),
},
}
pullRequests, err := ListPullRequests(t.Context(), provider, filters)
@@ -178,7 +174,7 @@ func TestFilterTitleMatch(t *testing.T) {
)
filters := []argoprojiov1alpha1.PullRequestGeneratorFilter{
{
TitleMatch: strp("\\[filter]"),
TitleMatch: new("\\[filter]"),
},
}
pullRequests, err := ListPullRequests(t.Context(), provider, filters)
@@ -228,10 +224,10 @@ func TestMultiFilterOrWithTitle(t *testing.T) {
)
filters := []argoprojiov1alpha1.PullRequestGeneratorFilter{
{
TitleMatch: strp("\\[filter]"),
TitleMatch: new("\\[filter]"),
},
{
TitleMatch: strp("- filter"),
TitleMatch: new("- filter"),
},
}
pullRequests, err := ListPullRequests(t.Context(), provider, filters)
@@ -282,10 +278,10 @@ func TestMultiFilterOr(t *testing.T) {
)
filters := []argoprojiov1alpha1.PullRequestGeneratorFilter{
{
BranchMatch: strp("w"),
BranchMatch: new("w"),
},
{
BranchMatch: strp("r"),
BranchMatch: new("r"),
},
}
pullRequests, err := ListPullRequests(t.Context(), provider, filters)
@@ -345,19 +341,19 @@ func TestMultiFilterOrWithTargetBranchFilterOrWithTitleFilter(t *testing.T) {
)
filters := []argoprojiov1alpha1.PullRequestGeneratorFilter{
{
BranchMatch: strp("w"),
TargetBranchMatch: strp("1"),
BranchMatch: new("w"),
TargetBranchMatch: new("1"),
},
{
BranchMatch: strp("r"),
TargetBranchMatch: strp("3"),
BranchMatch: new("r"),
TargetBranchMatch: new("3"),
},
{
TitleMatch: strp("two"),
TitleMatch: new("two"),
},
{
BranchMatch: strp("five"),
TitleMatch: strp("PR title is different than branch name"),
BranchMatch: new("five"),
TitleMatch: new("PR title is different than branch name"),
},
}
pullRequests, err := ListPullRequests(t.Context(), provider, filters)

View File

@@ -10,16 +10,19 @@ import (
"slices"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/arn"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/codecommit"
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
rgsatypes "github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi/types"
"github.com/aws/aws-sdk-go-v2/service/sts"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/aws/arn"
"github.com/aws/aws-sdk-go-v2/credentials/stscreds"
"github.com/aws/aws-sdk-go-v2/service/codecommit"
codecommittypes "github.com/aws/aws-sdk-go-v2/service/codecommit/types"
"github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi"
log "github.com/sirupsen/logrus"
"github.com/aws/aws-sdk-go-v2/config"
application "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
)
@@ -32,16 +35,16 @@ const (
// AWSCodeCommitClient is a lean facade to the codecommitiface.CodeCommitAPI
// it helps to reduce the mockery generated code.
type AWSCodeCommitClient interface {
ListRepositoriesWithContext(aws.Context, *codecommit.ListRepositoriesInput, ...request.Option) (*codecommit.ListRepositoriesOutput, error)
GetRepositoryWithContext(aws.Context, *codecommit.GetRepositoryInput, ...request.Option) (*codecommit.GetRepositoryOutput, error)
ListBranchesWithContext(aws.Context, *codecommit.ListBranchesInput, ...request.Option) (*codecommit.ListBranchesOutput, error)
GetFolderWithContext(aws.Context, *codecommit.GetFolderInput, ...request.Option) (*codecommit.GetFolderOutput, error)
ListRepositories(context.Context, *codecommit.ListRepositoriesInput, ...func(*codecommit.Options)) (*codecommit.ListRepositoriesOutput, error)
GetRepository(context.Context, *codecommit.GetRepositoryInput, ...func(*codecommit.Options)) (*codecommit.GetRepositoryOutput, error)
ListBranches(context.Context, *codecommit.ListBranchesInput, ...func(*codecommit.Options)) (*codecommit.ListBranchesOutput, error)
GetFolder(context.Context, *codecommit.GetFolderInput, ...func(*codecommit.Options)) (*codecommit.GetFolderOutput, error)
}
// AWSTaggingClient is a lean facade to the resourcegroupstaggingapiiface.ResourceGroupsTaggingAPIAPI
// it helps to reduce the mockery generated code.
type AWSTaggingClient interface {
GetResourcesWithContext(aws.Context, *resourcegroupstaggingapi.GetResourcesInput, ...request.Option) (*resourcegroupstaggingapi.GetResourcesOutput, error)
GetResources(context.Context, *resourcegroupstaggingapi.GetResourcesInput, ...func(*resourcegroupstaggingapi.Options)) (*resourcegroupstaggingapi.GetResourcesOutput, error)
}
type AWSCodeCommitProvider struct {
@@ -73,7 +76,7 @@ func (p *AWSCodeCommitProvider) ListRepos(ctx context.Context, cloneProtocol str
}
for _, repoName := range repoNames {
repo, err := p.codeCommitClient.GetRepositoryWithContext(ctx, &codecommit.GetRepositoryInput{
repo, err := p.codeCommitClient.GetRepository(ctx, &codecommit.GetRepositoryInput{
RepositoryName: aws.String(repoName),
})
if err != nil {
@@ -85,7 +88,7 @@ func (p *AWSCodeCommitProvider) ListRepos(ctx context.Context, cloneProtocol str
log.Warnf("codecommit returned invalid response for repository %s, skipped", repoName)
continue
}
if aws.StringValue(repo.RepositoryMetadata.DefaultBranch) == "" {
if aws.ToString(repo.RepositoryMetadata.DefaultBranch) == "" {
// if a codecommit repo doesn't have default branch, it's uninitialized. not going to bother with it.
log.Warnf("repository %s does not have default branch, skipped", repoName)
continue
@@ -94,11 +97,11 @@ func (p *AWSCodeCommitProvider) ListRepos(ctx context.Context, cloneProtocol str
switch cloneProtocol {
// default to SSH if unspecified (i.e. if "").
case "", "ssh":
url = aws.StringValue(repo.RepositoryMetadata.CloneUrlSsh)
url = aws.ToString(repo.RepositoryMetadata.CloneUrlSsh)
case "https":
url = aws.StringValue(repo.RepositoryMetadata.CloneUrlHttp)
url = aws.ToString(repo.RepositoryMetadata.CloneUrlHttp)
case "https-fips":
url, err = getCodeCommitFIPSEndpoint(aws.StringValue(repo.RepositoryMetadata.CloneUrlHttp))
url, err = getCodeCommitFIPSEndpoint(aws.ToString(repo.RepositoryMetadata.CloneUrlHttp))
if err != nil {
return nil, fmt.Errorf("https-fips is provided but repoUrl can't be transformed to FIPS endpoint: %w", err)
}
@@ -108,13 +111,13 @@ func (p *AWSCodeCommitProvider) ListRepos(ctx context.Context, cloneProtocol str
repos = append(repos, &Repository{
// there's no "organization" level at codecommit.
// we are just using AWS accountId for now.
Organization: aws.StringValue(repo.RepositoryMetadata.AccountId),
Repository: aws.StringValue(repo.RepositoryMetadata.RepositoryName),
Organization: aws.ToString(repo.RepositoryMetadata.AccountId),
Repository: aws.ToString(repo.RepositoryMetadata.RepositoryName),
URL: url,
Branch: aws.StringValue(repo.RepositoryMetadata.DefaultBranch),
Branch: aws.ToString(repo.RepositoryMetadata.DefaultBranch),
// we could propagate repo tag keys, but without value not sure if it's any useful.
Labels: []string{},
RepositoryId: aws.StringValue(repo.RepositoryMetadata.RepositoryId),
RepositoryId: aws.ToString(repo.RepositoryMetadata.RepositoryId),
})
}
@@ -142,13 +145,9 @@ func (p *AWSCodeCommitProvider) RepoHasPath(ctx context.Context, repo *Repositor
FolderPath: aws.String(parentPath),
RepositoryName: aws.String(repo.Repository),
}
output, err := p.codeCommitClient.GetFolderWithContext(ctx, input)
output, err := p.codeCommitClient.GetFolder(ctx, input)
if err != nil {
if hasAwsError(err,
codecommit.ErrCodeRepositoryDoesNotExistException,
codecommit.ErrCodeCommitDoesNotExistException,
codecommit.ErrCodeFolderDoesNotExistException,
) {
if hasAwsError(err) {
return false, nil
}
// unhandled exception, propagate out
@@ -157,22 +156,22 @@ func (p *AWSCodeCommitProvider) RepoHasPath(ctx context.Context, repo *Repositor
// anything that matches.
for _, submodule := range output.SubModules {
if basePath == aws.StringValue(submodule.RelativePath) {
if basePath == aws.ToString(submodule.RelativePath) {
return true, nil
}
}
for _, subpath := range output.SubFolders {
if basePath == aws.StringValue(subpath.RelativePath) {
if basePath == aws.ToString(subpath.RelativePath) {
return true, nil
}
}
for _, subpath := range output.Files {
if basePath == aws.StringValue(subpath.RelativePath) {
if basePath == aws.ToString(subpath.RelativePath) {
return true, nil
}
}
for _, subpath := range output.SymbolicLinks {
if basePath == aws.StringValue(subpath.RelativePath) {
if basePath == aws.ToString(subpath.RelativePath) {
return true, nil
}
}
@@ -182,7 +181,7 @@ func (p *AWSCodeCommitProvider) RepoHasPath(ctx context.Context, repo *Repositor
func (p *AWSCodeCommitProvider) GetBranches(ctx context.Context, repo *Repository) ([]*Repository, error) {
repos := make([]*Repository, 0)
if !p.allBranches {
output, err := p.codeCommitClient.GetRepositoryWithContext(ctx, &codecommit.GetRepositoryInput{
output, err := p.codeCommitClient.GetRepository(ctx, &codecommit.GetRepositoryInput{
RepositoryName: aws.String(repo.Repository),
})
if err != nil {
@@ -192,7 +191,7 @@ func (p *AWSCodeCommitProvider) GetBranches(ctx context.Context, repo *Repositor
Organization: repo.Organization,
Repository: repo.Repository,
URL: repo.URL,
Branch: aws.StringValue(output.RepositoryMetadata.DefaultBranch),
Branch: aws.ToString(output.RepositoryMetadata.DefaultBranch),
RepositoryId: repo.RepositoryId,
Labels: repo.Labels,
// getting SHA of the branch requires a separate GetBranch call.
@@ -204,7 +203,7 @@ func (p *AWSCodeCommitProvider) GetBranches(ctx context.Context, repo *Repositor
RepositoryName: aws.String(repo.Repository),
}
for {
output, err := p.codeCommitClient.ListBranchesWithContext(ctx, input)
output, err := p.codeCommitClient.ListBranches(ctx, input)
if err != nil {
return nil, err
}
@@ -213,7 +212,7 @@ func (p *AWSCodeCommitProvider) GetBranches(ctx context.Context, repo *Repositor
Organization: repo.Organization,
Repository: repo.Repository,
URL: repo.URL,
Branch: aws.StringValue(branch),
Branch: branch,
RepositoryId: repo.RepositoryId,
Labels: repo.Labels,
// getting SHA of the branch requires a separate GetBranch call.
@@ -222,7 +221,7 @@ func (p *AWSCodeCommitProvider) GetBranches(ctx context.Context, repo *Repositor
})
}
input.NextToken = output.NextToken
if aws.StringValue(output.NextToken) == "" {
if aws.ToString(output.NextToken) == "" {
break
}
}
@@ -241,32 +240,32 @@ func (p *AWSCodeCommitProvider) listRepoNames(ctx context.Context) ([]string, er
listReposInput := &codecommit.ListRepositoriesInput{}
var output *codecommit.ListRepositoriesOutput
for {
output, err = p.codeCommitClient.ListRepositoriesWithContext(ctx, listReposInput)
output, err = p.codeCommitClient.ListRepositories(ctx, listReposInput)
if err != nil {
break
}
for _, repo := range output.Repositories {
repoNames = append(repoNames, aws.StringValue(repo.RepositoryName))
repoNames = append(repoNames, aws.ToString(repo.RepositoryName))
}
listReposInput.NextToken = output.NextToken
if aws.StringValue(output.NextToken) == "" {
if aws.ToString(output.NextToken) == "" {
break
}
}
} else {
log.Debugf("tag filer is specified, calling tagging api to list repos")
discoveryInput := &resourcegroupstaggingapi.GetResourcesInput{
ResourceTypeFilters: aws.StringSlice([]string{resourceTypeCodeCommitRepository}),
ResourceTypeFilters: []string{resourceTypeCodeCommitRepository},
TagFilters: tagFilters,
}
var output *resourcegroupstaggingapi.GetResourcesOutput
for {
output, err = p.taggingClient.GetResourcesWithContext(ctx, discoveryInput)
output, err = p.taggingClient.GetResources(ctx, discoveryInput)
if err != nil {
break
}
for _, resource := range output.ResourceTagMappingList {
repoArn := aws.StringValue(resource.ResourceARN)
repoArn := aws.ToString(resource.ResourceARN)
log.Debugf("discovered codecommit repo with arn %s", repoArn)
repoName, extractErr := getCodeCommitRepoName(repoArn)
if extractErr != nil {
@@ -276,7 +275,7 @@ func (p *AWSCodeCommitProvider) listRepoNames(ctx context.Context) ([]string, er
repoNames = append(repoNames, repoName)
}
discoveryInput.PaginationToken = output.PaginationToken
if aws.StringValue(output.PaginationToken) == "" {
if aws.ToString(output.PaginationToken) == "" {
break
}
}
@@ -284,19 +283,20 @@ func (p *AWSCodeCommitProvider) listRepoNames(ctx context.Context) ([]string, er
return repoNames, err
}
func (p *AWSCodeCommitProvider) getTagFilters() []*resourcegroupstaggingapi.TagFilter {
filters := make(map[string]*resourcegroupstaggingapi.TagFilter)
// getTagFilters filters by tag
func (p *AWSCodeCommitProvider) getTagFilters() []rgsatypes.TagFilter {
filters := make(map[string]rgsatypes.TagFilter)
for _, tagFilter := range p.tagFilters {
filter, hasKey := filters[tagFilter.Key]
if !hasKey {
filter = &resourcegroupstaggingapi.TagFilter{
filter := filters[tagFilter.Key]
if filter.Key == nil {
filter = rgsatypes.TagFilter{
Key: aws.String(tagFilter.Key),
}
filters[tagFilter.Key] = filter
}
if tagFilter.Value != "" {
filter.Values = append(filter.Values, aws.String(tagFilter.Value))
filter.Values = append(filter.Values, tagFilter.Value)
}
filters[tagFilter.Key] = filter
}
return slices.Collect(maps.Values(filters))
}
@@ -326,12 +326,15 @@ func getCodeCommitFIPSEndpoint(repoURL string) (string, error) {
return strings.Replace(repoURL, prefixGitURLHTTPS, prefixGitURLHTTPSFIPS, 1), nil
}
func hasAwsError(err error, codes ...string) bool {
var awsErr awserr.Error
if errors.As(err, &awsErr) {
return slices.Contains(codes, awsErr.Code())
}
return false
func hasAwsError(err error) bool {
// Check for common CodeCommit exceptions using SDK v2 typed errors
var repoNotFound *codecommittypes.RepositoryDoesNotExistException
var commitNotFound *codecommittypes.CommitDoesNotExistException
var folderNotFound *codecommittypes.FolderDoesNotExistException
return errors.As(err, &repoNotFound) ||
errors.As(err, &commitNotFound) ||
errors.As(err, &folderNotFound)
}
// toAbsolutePath transforms a path input to absolute path, as required by AWS CodeCommit
@@ -343,37 +346,32 @@ func toAbsolutePath(path string) string {
return filepath.ToSlash(filepath.Join("/", path)) //nolint:gocritic // Prepend slash to have an absolute path
}
func createAWSDiscoveryClients(_ context.Context, role string, region string) (*resourcegroupstaggingapi.ResourceGroupsTaggingAPI, *codecommit.CodeCommit, error) {
podSession, err := session.NewSession()
if err != nil {
return nil, nil, fmt.Errorf("error creating new AWS pod session: %w", err)
}
discoverySession := podSession
// assume role if provided - this allows cross account CodeCommit repo discovery.
if role != "" {
log.Debugf("role %s is provided for AWS CodeCommit discovery", role)
assumeRoleCreds := stscreds.NewCredentials(podSession, role)
discoverySession, err = session.NewSession(&aws.Config{
Credentials: assumeRoleCreds,
})
if err != nil {
return nil, nil, fmt.Errorf("error creating new AWS discovery session: %w", err)
}
} else {
log.Debugf("role is not provided for AWS CodeCommit discovery, using pod role")
}
// use region explicitly if provided - this allows cross region CodeCommit repo discovery.
// createAWSDiscoveryClients creates AWS clients
func createAWSDiscoveryClients(ctx context.Context, role string, region string) (*resourcegroupstaggingapi.Client, *codecommit.Client, error) {
var configOpts []func(*config.LoadOptions) error
if region != "" {
log.Debugf("region %s is provided for AWS CodeCommit discovery", region)
discoverySession = discoverySession.Copy(&aws.Config{
Region: aws.String(region),
})
configOpts = append(configOpts, config.WithRegion(region))
} else {
log.Debugf("region is not provided for AWS CodeCommit discovery, using pod region")
}
// Load the default config based on config options
cfg, err := config.LoadDefaultConfig(ctx, configOpts...)
if err != nil {
return nil, nil, fmt.Errorf("error loading default config: %w", err)
}
client := sts.NewFromConfig(cfg)
// assume role if provided - this allows cross account CodeCommit repo discovery.
if role != "" {
log.Debugf("role %s is provided for AWS CodeCommit discovery", role)
assumeRoleCreds := stscreds.NewAssumeRoleProvider(client, role)
cfg.Credentials = aws.NewCredentialsCache(assumeRoleCreds)
} else {
log.Debugf("role is not provided for AWS CodeCommit discovery, using pod role")
}
taggingClient := resourcegroupstaggingapi.New(discoverySession)
codeCommitClient := codecommit.New(discoverySession)
taggingClient := resourcegroupstaggingapi.NewFromConfig(cfg)
codeCommitClient := codecommit.NewFromConfig(cfg)
return taggingClient, codeCommitClient, nil
}

View File

@@ -5,10 +5,13 @@ import (
"sort"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/codecommit"
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/codecommit"
codecommittypes "github.com/aws/aws-sdk-go-v2/service/codecommit/types"
"github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi"
rgsatypes "github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi/types"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
@@ -34,7 +37,7 @@ func TestAWSCodeCommitListRepos(t *testing.T) {
repositories []*awsCodeCommitTestRepository
cloneProtocol string
tagFilters []*v1alpha1.TagFilter
expectTagFilters []*resourcegroupstaggingapi.TagFilter
expectTagFilters []rgsatypes.TagFilter
listRepositoryError error
expectOverallError bool
expectListAtCodeCommit bool
@@ -57,8 +60,8 @@ func TestAWSCodeCommitListRepos(t *testing.T) {
{Key: "key1", Value: "value2"},
{Key: "key2"},
},
expectTagFilters: []*resourcegroupstaggingapi.TagFilter{
{Key: aws.String("key1"), Values: aws.StringSlice([]string{"value1", "value2"})},
expectTagFilters: []rgsatypes.TagFilter{
{Key: aws.String("key1"), Values: []string{"value1", "value2"}},
{Key: aws.String("key2")},
},
expectOverallError: false,
@@ -80,7 +83,7 @@ func TestAWSCodeCommitListRepos(t *testing.T) {
tagFilters: []*v1alpha1.TagFilter{
{Key: "key1"},
},
expectTagFilters: []*resourcegroupstaggingapi.TagFilter{
expectTagFilters: []rgsatypes.TagFilter{
{Key: aws.String("key1")},
},
expectOverallError: false,
@@ -160,12 +163,12 @@ func TestAWSCodeCommitListRepos(t *testing.T) {
codeCommitClient := mocks.NewAWSCodeCommitClient(t)
taggingClient := mocks.NewAWSTaggingClient(t)
ctx := t.Context()
codecommitRepoNameIdPairs := make([]*codecommit.RepositoryNameIdPair, 0)
resourceTaggings := make([]*resourcegroupstaggingapi.ResourceTagMapping, 0)
codecommitRepoNameIdPairs := make([]codecommittypes.RepositoryNameIdPair, 0)
resourceTaggings := make([]rgsatypes.ResourceTagMapping, 0)
validRepositories := make([]*awsCodeCommitTestRepository, 0)
for _, repo := range testCase.repositories {
repoMetadata := &codecommit.RepositoryMetadata{
repoMetadata := &codecommittypes.RepositoryMetadata{
AccountId: aws.String(repo.accountId),
Arn: aws.String(repo.arn),
CloneUrlHttp: aws.String("https://git-codecommit.us-east-1.amazonaws.com/v1/repos/" + repo.name),
@@ -177,13 +180,13 @@ func TestAWSCodeCommitListRepos(t *testing.T) {
if repo.getRepositoryNilMetadata {
repoMetadata = nil
}
codeCommitClient.EXPECT().GetRepositoryWithContext(mock.Anything, &codecommit.GetRepositoryInput{RepositoryName: aws.String(repo.name)}).
codeCommitClient.EXPECT().GetRepository(mock.Anything, &codecommit.GetRepositoryInput{RepositoryName: aws.String(repo.name)}).
Return(&codecommit.GetRepositoryOutput{RepositoryMetadata: repoMetadata}, repo.getRepositoryError).Maybe()
codecommitRepoNameIdPairs = append(codecommitRepoNameIdPairs, &codecommit.RepositoryNameIdPair{
codecommitRepoNameIdPairs = append(codecommitRepoNameIdPairs, codecommittypes.RepositoryNameIdPair{
RepositoryId: aws.String(repo.id),
RepositoryName: aws.String(repo.name),
})
resourceTaggings = append(resourceTaggings, &resourcegroupstaggingapi.ResourceTagMapping{
resourceTaggings = append(resourceTaggings, rgsatypes.ResourceTagMapping{
ResourceARN: aws.String(repo.arn),
})
if repo.valid {
@@ -192,14 +195,14 @@ func TestAWSCodeCommitListRepos(t *testing.T) {
}
if testCase.expectListAtCodeCommit {
codeCommitClient.EXPECT().ListRepositoriesWithContext(mock.Anything, &codecommit.ListRepositoriesInput{}).
codeCommitClient.EXPECT().ListRepositories(mock.Anything, &codecommit.ListRepositoriesInput{}).
Return(&codecommit.ListRepositoriesOutput{
Repositories: codecommitRepoNameIdPairs,
}, testCase.listRepositoryError).Maybe()
} else {
taggingClient.EXPECT().GetResourcesWithContext(mock.Anything, mock.MatchedBy(equalIgnoringTagFilterOrder(&resourcegroupstaggingapi.GetResourcesInput{
taggingClient.EXPECT().GetResources(mock.Anything, mock.MatchedBy(equalIgnoringTagFilterOrder(&resourcegroupstaggingapi.GetResourcesInput{
TagFilters: testCase.expectTagFilters,
ResourceTypeFilters: aws.StringSlice([]string{resourceTypeCodeCommitRepository}),
ResourceTypeFilters: []string{resourceTypeCodeCommitRepository},
}))).
Return(&resourcegroupstaggingapi.GetResourcesOutput{
ResourceTagMappingList: resourceTaggings,
@@ -249,7 +252,7 @@ func TestAWSCodeCommitRepoHasPath(t *testing.T) {
path: "lib/config.yaml",
expectedGetFolderPath: "/lib",
getFolderOutput: &codecommit.GetFolderOutput{
Files: []*codecommit.File{
Files: []codecommittypes.File{
{RelativePath: aws.String("config.yaml")},
},
},
@@ -261,7 +264,7 @@ func TestAWSCodeCommitRepoHasPath(t *testing.T) {
path: "lib/config",
expectedGetFolderPath: "/lib",
getFolderOutput: &codecommit.GetFolderOutput{
SubFolders: []*codecommit.Folder{
SubFolders: []codecommittypes.Folder{
{RelativePath: aws.String("config")},
},
},
@@ -273,7 +276,7 @@ func TestAWSCodeCommitRepoHasPath(t *testing.T) {
path: "/lib/submodule/",
expectedGetFolderPath: "/lib",
getFolderOutput: &codecommit.GetFolderOutput{
SubModules: []*codecommit.SubModule{
SubModules: []codecommittypes.SubModule{
{RelativePath: aws.String("submodule")},
},
},
@@ -285,7 +288,7 @@ func TestAWSCodeCommitRepoHasPath(t *testing.T) {
path: "./lib/service.json",
expectedGetFolderPath: "/lib",
getFolderOutput: &codecommit.GetFolderOutput{
SymbolicLinks: []*codecommit.SymbolicLink{
SymbolicLinks: []codecommittypes.SymbolicLink{
{RelativePath: aws.String("service.json")},
},
},
@@ -297,16 +300,16 @@ func TestAWSCodeCommitRepoHasPath(t *testing.T) {
path: "no-match.json",
expectedGetFolderPath: "/",
getFolderOutput: &codecommit.GetFolderOutput{
Files: []*codecommit.File{
Files: []codecommittypes.File{
{RelativePath: aws.String("config.yaml")},
},
SubFolders: []*codecommit.Folder{
SubFolders: []codecommittypes.Folder{
{RelativePath: aws.String("config")},
},
SubModules: []*codecommit.SubModule{
SubModules: []codecommittypes.SubModule{
{RelativePath: aws.String("submodule")},
},
SymbolicLinks: []*codecommit.SymbolicLink{
SymbolicLinks: []codecommittypes.SymbolicLink{
{RelativePath: aws.String("service.json")},
},
},
@@ -317,7 +320,7 @@ func TestAWSCodeCommitRepoHasPath(t *testing.T) {
name: "RepoHasPath when parent folder not found",
path: "lib/submodule",
expectedGetFolderPath: "/lib",
getFolderError: &codecommit.FolderDoesNotExistException{},
getFolderError: &codecommittypes.FolderDoesNotExistException{},
expectOverallError: false,
},
{
@@ -347,7 +350,7 @@ func TestAWSCodeCommitRepoHasPath(t *testing.T) {
taggingClient := mocks.NewAWSTaggingClient(t)
ctx := t.Context()
if testCase.expectedGetFolderPath != "" {
codeCommitClient.EXPECT().GetFolderWithContext(mock.Anything, &codecommit.GetFolderInput{
codeCommitClient.EXPECT().GetFolder(mock.Anything, &codecommit.GetFolderInput{
CommitSpecifier: aws.String(branch),
FolderPath: aws.String(testCase.expectedGetFolderPath),
RepositoryName: aws.String(repoName),
@@ -419,13 +422,15 @@ func TestAWSCodeCommitGetBranches(t *testing.T) {
taggingClient := mocks.NewAWSTaggingClient(t)
ctx := t.Context()
if testCase.allBranches {
codeCommitClient.EXPECT().ListBranchesWithContext(mock.Anything, &codecommit.ListBranchesInput{
branches := make([]string, len(testCase.branches))
copy(branches, testCase.branches)
codeCommitClient.EXPECT().ListBranches(mock.Anything, &codecommit.ListBranchesInput{
RepositoryName: aws.String(name),
}).
Return(&codecommit.ListBranchesOutput{Branches: aws.StringSlice(testCase.branches)}, testCase.apiError).Maybe()
Return(&codecommit.ListBranchesOutput{Branches: branches}, testCase.apiError).Maybe()
} else {
codeCommitClient.EXPECT().GetRepositoryWithContext(mock.Anything, &codecommit.GetRepositoryInput{RepositoryName: aws.String(name)}).
Return(&codecommit.GetRepositoryOutput{RepositoryMetadata: &codecommit.RepositoryMetadata{
codeCommitClient.EXPECT().GetRepository(mock.Anything, &codecommit.GetRepositoryInput{RepositoryName: aws.String(name)}).
Return(&codecommit.GetRepositoryOutput{RepositoryMetadata: &codecommittypes.RepositoryMetadata{
AccountId: aws.String(organization),
DefaultBranch: aws.String(defaultBranch),
}}, testCase.apiError).Maybe()
@@ -470,8 +475,22 @@ func TestAWSCodeCommitGetBranches(t *testing.T) {
func equalIgnoringTagFilterOrder(expected *resourcegroupstaggingapi.GetResourcesInput) func(*resourcegroupstaggingapi.GetResourcesInput) bool {
return func(actual *resourcegroupstaggingapi.GetResourcesInput) bool {
sort.Slice(actual.TagFilters, func(i, j int) bool {
return *actual.TagFilters[i].Key < *actual.TagFilters[j].Key
keyI := ""
keyJ := ""
if actual.TagFilters[i].Key != nil {
keyI = *actual.TagFilters[i].Key
}
if actual.TagFilters[j].Key != nil {
keyJ = *actual.TagFilters[j].Key
}
return keyI < keyJ
})
return cmp.Equal(expected, actual)
// Ignore unexported fields in AWS SDK v2 types
return cmp.Equal(expected, actual,
cmpopts.IgnoreUnexported(
rgsatypes.TagFilter{},
resourcegroupstaggingapi.GetResourcesInput{},
),
)
}
}

View File

@@ -9,7 +9,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"k8s.io/utils/ptr"
"github.com/microsoft/azure-devops-go-api/azuredevops/v7"
azureGit "github.com/microsoft/azure-devops-go-api/azuredevops/v7/git"
@@ -18,10 +17,6 @@ import (
"github.com/argoproj/argo-cd/v3/applicationset/services/scm_provider/mocks"
)
func s(input string) *string {
return ptr.To(input)
}
func TestAzureDevopsRepoHasPath(t *testing.T) {
organization := "myorg"
teamProject := "myorg_project"
@@ -51,12 +46,12 @@ func TestAzureDevopsRepoHasPath(t *testing.T) {
{
name: "RepoHasPath when no path found returns false",
pathFound: false,
azureDevopsError: azuredevops.WrappedError{TypeKey: s(AzureDevOpsErrorsTypeKeyValues.GitItemNotFound)},
azureDevopsError: azuredevops.WrappedError{TypeKey: new(AzureDevOpsErrorsTypeKeyValues.GitItemNotFound)},
},
{
name: "RepoHasPath when unknown Azure DevOps WrappedError occurs returns error",
pathFound: false,
azureDevopsError: azuredevops.WrappedError{TypeKey: s("OtherAzureDevopsException")},
azureDevopsError: azuredevops.WrappedError{TypeKey: new("OtherAzureDevopsException")},
returnError: true,
errorMessage: "failed to check for path existence",
},
@@ -124,12 +119,12 @@ func TestGetDefaultBranchOnDisabledRepo(t *testing.T) {
}{
{
name: "azure devops error when disabled repo causes empty return value",
azureDevOpsError: azuredevops.WrappedError{TypeKey: s(AzureDevOpsErrorsTypeKeyValues.GitRepositoryNotFound)},
azureDevOpsError: azuredevops.WrappedError{TypeKey: new(AzureDevOpsErrorsTypeKeyValues.GitRepositoryNotFound)},
shouldReturnError: false,
},
{
name: "azure devops error with unknown error type returns error",
azureDevOpsError: azuredevops.WrappedError{TypeKey: s("OtherError")},
azureDevOpsError: azuredevops.WrappedError{TypeKey: new("OtherError")},
shouldReturnError: true,
},
{
@@ -181,12 +176,12 @@ func TestGetAllBranchesOnDisabledRepo(t *testing.T) {
}{
{
name: "azure devops error when disabled repo causes empty return value",
azureDevOpsError: azuredevops.WrappedError{TypeKey: s(AzureDevOpsErrorsTypeKeyValues.GitRepositoryNotFound)},
azureDevOpsError: azuredevops.WrappedError{TypeKey: new(AzureDevOpsErrorsTypeKeyValues.GitRepositoryNotFound)},
shouldReturnError: false,
},
{
name: "azure devops error with unknown error type returns error",
azureDevOpsError: azuredevops.WrappedError{TypeKey: s("OtherError")},
azureDevOpsError: azuredevops.WrappedError{TypeKey: new("OtherError")},
shouldReturnError: true,
},
{
@@ -234,7 +229,7 @@ func TestAzureDevOpsGetDefaultBranchStripsRefsName(t *testing.T) {
strippedBranchName := "somebranch"
defaultBranch := fmt.Sprintf("refs/heads/%v", strippedBranchName)
branchReturn := &azureGit.GitBranchStats{Name: &strippedBranchName, Commit: &azureGit.GitCommitRef{CommitId: s("abc123233223")}}
branchReturn := &azureGit.GitBranchStats{Name: &strippedBranchName, Commit: &azureGit.GitCommitRef{CommitId: new("abc123233223")}}
repo := &Repository{Organization: organization, Repository: repoName, RepositoryId: uuid, Branch: defaultBranch}
gitClientMock := &azureMock.Client{}
@@ -273,7 +268,7 @@ func TestAzureDevOpsGetBranchesDefultBranchOnly(t *testing.T) {
}{
{
name: "GetBranches AllBranches false when single branch returned returns branch",
expectedBranch: &azureGit.GitBranchStats{Name: &defaultBranch, Commit: &azureGit.GitCommitRef{CommitId: s("abc123233223")}},
expectedBranch: &azureGit.GitBranchStats{Name: &defaultBranch, Commit: &azureGit.GitCommitRef{CommitId: new("abc123233223")}},
},
{
name: "GetBranches AllBranches false when request fails returns error and empty result",
@@ -285,7 +280,7 @@ func TestAzureDevOpsGetBranchesDefultBranchOnly(t *testing.T) {
},
{
name: "GetBranches AllBranches false when branch returned with long commit SHA",
expectedBranch: &azureGit.GitBranchStats{Name: &defaultBranch, Commit: &azureGit.GitCommitRef{CommitId: s("53863052ADF24229AB72154B4D83DAB7")}},
expectedBranch: &azureGit.GitBranchStats{Name: &defaultBranch, Commit: &azureGit.GitCommitRef{CommitId: new("53863052ADF24229AB72154B4D83DAB7")}},
},
}
@@ -344,7 +339,7 @@ func TestAzureDevopsGetBranches(t *testing.T) {
}{
{
name: "GetBranches when single branch returned returns this branch info",
expectedBranches: &[]azureGit.GitBranchStats{{Name: s("feature-feat1"), Commit: &azureGit.GitCommitRef{CommitId: s("abc123233223")}}},
expectedBranches: &[]azureGit.GitBranchStats{{Name: new("feature-feat1"), Commit: &azureGit.GitCommitRef{CommitId: new("abc123233223")}}},
allBranches: true,
},
{
@@ -365,9 +360,9 @@ func TestAzureDevopsGetBranches(t *testing.T) {
{
name: "GetBranches when multiple branches returned returns branch info for all branches",
expectedBranches: &[]azureGit.GitBranchStats{
{Name: s("feature-feat1"), Commit: &azureGit.GitCommitRef{CommitId: s("abc123233223")}},
{Name: s("feature/feat2"), Commit: &azureGit.GitCommitRef{CommitId: s("4334")}},
{Name: s("feature/feat2"), Commit: &azureGit.GitCommitRef{CommitId: s("53863052ADF24229AB72154B4D83DAB7")}},
{Name: new("feature-feat1"), Commit: &azureGit.GitCommitRef{CommitId: new("abc123233223")}},
{Name: new("feature/feat2"), Commit: &azureGit.GitCommitRef{CommitId: new("4334")}},
{Name: new("feature/feat2"), Commit: &azureGit.GitCommitRef{CommitId: new("53863052ADF24229AB72154B4D83DAB7")}},
},
allBranches: true,
},
@@ -434,12 +429,12 @@ func TestGetAzureDevopsRepositories(t *testing.T) {
}{
{
name: "ListRepos when single repo found returns repo info",
repositories: []azureGit.GitRepository{{Name: s("repo1"), DefaultBranch: s("main"), RemoteUrl: s("https://remoteurl.u"), Id: repoId}},
repositories: []azureGit.GitRepository{{Name: new("repo1"), DefaultBranch: new("main"), RemoteUrl: new("https://remoteurl.u"), Id: repoId}},
expectedNumberOfRepos: 1,
},
{
name: "ListRepos when repo has no default branch returns empty list",
repositories: []azureGit.GitRepository{{Name: s("repo2"), RemoteUrl: s("https://remoteurl.u"), Id: repoId}},
repositories: []azureGit.GitRepository{{Name: new("repo2"), RemoteUrl: new("https://remoteurl.u"), Id: repoId}},
},
{
name: "ListRepos when Azure DevOps request fails returns error",
@@ -447,24 +442,24 @@ func TestGetAzureDevopsRepositories(t *testing.T) {
},
{
name: "ListRepos when repo has no name returns empty list",
repositories: []azureGit.GitRepository{{DefaultBranch: s("main"), RemoteUrl: s("https://remoteurl.u"), Id: repoId}},
repositories: []azureGit.GitRepository{{DefaultBranch: new("main"), RemoteUrl: new("https://remoteurl.u"), Id: repoId}},
},
{
name: "ListRepos when repo has no remote URL returns empty list",
repositories: []azureGit.GitRepository{{DefaultBranch: s("main"), Name: s("repo_name"), Id: repoId}},
repositories: []azureGit.GitRepository{{DefaultBranch: new("main"), Name: new("repo_name"), Id: repoId}},
},
{
name: "ListRepos when repo has no ID returns empty list",
repositories: []azureGit.GitRepository{{DefaultBranch: s("main"), Name: s("repo_name"), RemoteUrl: s("https://remoteurl.u")}},
repositories: []azureGit.GitRepository{{DefaultBranch: new("main"), Name: new("repo_name"), RemoteUrl: new("https://remoteurl.u")}},
},
{
name: "ListRepos when multiple repos returned returns list of eligible repos only",
repositories: []azureGit.GitRepository{
{Name: s("returned1"), DefaultBranch: s("main"), RemoteUrl: s("https://remoteurl.u"), Id: repoId},
{Name: s("missing_default_branch"), RemoteUrl: s("https://remoteurl.u"), Id: repoId},
{DefaultBranch: s("missing_name"), RemoteUrl: s("https://remoteurl.u"), Id: repoId},
{Name: s("missing_remote_url"), DefaultBranch: s("main"), Id: repoId},
{Name: s("missing_id"), DefaultBranch: s("main"), RemoteUrl: s("https://remoteurl.u")},
{Name: new("returned1"), DefaultBranch: new("main"), RemoteUrl: new("https://remoteurl.u"), Id: repoId},
{Name: new("missing_default_branch"), RemoteUrl: new("https://remoteurl.u"), Id: repoId},
{DefaultBranch: new("missing_name"), RemoteUrl: new("https://remoteurl.u"), Id: repoId},
{Name: new("missing_remote_url"), DefaultBranch: new("main"), Id: repoId},
{Name: new("missing_id"), DefaultBranch: new("main"), RemoteUrl: new("https://remoteurl.u")},
},
expectedNumberOfRepos: 1,
},
@@ -473,7 +468,7 @@ func TestGetAzureDevopsRepositories(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
gitClientMock := azureMock.NewClient(t)
gitClientMock.EXPECT().GetRepositories(mock.Anything, azureGit.GetRepositoriesArgs{Project: s(teamProject)}).Return(&testCase.repositories, testCase.getRepositoriesError)
gitClientMock.EXPECT().GetRepositories(mock.Anything, azureGit.GetRepositoriesArgs{Project: new(teamProject)}).Return(&testCase.repositories, testCase.getRepositoriesError)
clientFactoryMock := &mocks.AzureDevOpsClientFactory{}
clientFactoryMock.EXPECT().GetClient(mock.Anything).Return(gitClientMock, nil)

View File

@@ -445,7 +445,6 @@ func TestListReposTLS(t *testing.T) {
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defaultHandler(t)(w, r)

View File

@@ -1100,7 +1100,7 @@ func TestGitlabListRepos(t *testing.T) {
url: "git@gitlab.com:test-argocd-proton/argocd.git",
filters: []v1alpha1.SCMProviderGeneratorFilter{
{
LabelMatch: strp("test-topic"),
LabelMatch: new("test-topic"),
},
},
},
@@ -1301,7 +1301,6 @@ func TestGetBranchesTLS(t *testing.T) {
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
gitlabMockHandler(t)(w, r)

View File

@@ -5,9 +5,9 @@
package mocks
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/service/codecommit"
"context"
"github.com/aws/aws-sdk-go-v2/service/codecommit"
mock "github.com/stretchr/testify/mock"
)
@@ -38,71 +38,71 @@ func (_m *AWSCodeCommitClient) EXPECT() *AWSCodeCommitClient_Expecter {
return &AWSCodeCommitClient_Expecter{mock: &_m.Mock}
}
// GetFolderWithContext provides a mock function for the type AWSCodeCommitClient
func (_mock *AWSCodeCommitClient) GetFolderWithContext(v aws.Context, getFolderInput *codecommit.GetFolderInput, options ...request.Option) (*codecommit.GetFolderOutput, error) {
// request.Option
_va := make([]interface{}, len(options))
for _i := range options {
_va[_i] = options[_i]
// GetFolder provides a mock function for the type AWSCodeCommitClient
func (_mock *AWSCodeCommitClient) GetFolder(context1 context.Context, getFolderInput *codecommit.GetFolderInput, fns ...func(*codecommit.Options)) (*codecommit.GetFolderOutput, error) {
// func(*codecommit.Options)
_va := make([]interface{}, len(fns))
for _i := range fns {
_va[_i] = fns[_i]
}
var _ca []interface{}
_ca = append(_ca, v, getFolderInput)
_ca = append(_ca, context1, getFolderInput)
_ca = append(_ca, _va...)
ret := _mock.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for GetFolderWithContext")
panic("no return value specified for GetFolder")
}
var r0 *codecommit.GetFolderOutput
var r1 error
if returnFunc, ok := ret.Get(0).(func(aws.Context, *codecommit.GetFolderInput, ...request.Option) (*codecommit.GetFolderOutput, error)); ok {
return returnFunc(v, getFolderInput, options...)
if returnFunc, ok := ret.Get(0).(func(context.Context, *codecommit.GetFolderInput, ...func(*codecommit.Options)) (*codecommit.GetFolderOutput, error)); ok {
return returnFunc(context1, getFolderInput, fns...)
}
if returnFunc, ok := ret.Get(0).(func(aws.Context, *codecommit.GetFolderInput, ...request.Option) *codecommit.GetFolderOutput); ok {
r0 = returnFunc(v, getFolderInput, options...)
if returnFunc, ok := ret.Get(0).(func(context.Context, *codecommit.GetFolderInput, ...func(*codecommit.Options)) *codecommit.GetFolderOutput); ok {
r0 = returnFunc(context1, getFolderInput, fns...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*codecommit.GetFolderOutput)
}
}
if returnFunc, ok := ret.Get(1).(func(aws.Context, *codecommit.GetFolderInput, ...request.Option) error); ok {
r1 = returnFunc(v, getFolderInput, options...)
if returnFunc, ok := ret.Get(1).(func(context.Context, *codecommit.GetFolderInput, ...func(*codecommit.Options)) error); ok {
r1 = returnFunc(context1, getFolderInput, fns...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// AWSCodeCommitClient_GetFolderWithContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFolderWithContext'
type AWSCodeCommitClient_GetFolderWithContext_Call struct {
// AWSCodeCommitClient_GetFolder_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFolder'
type AWSCodeCommitClient_GetFolder_Call struct {
*mock.Call
}
// GetFolderWithContext is a helper method to define mock.On call
// - v aws.Context
// GetFolder is a helper method to define mock.On call
// - context1 context.Context
// - getFolderInput *codecommit.GetFolderInput
// - options ...request.Option
func (_e *AWSCodeCommitClient_Expecter) GetFolderWithContext(v interface{}, getFolderInput interface{}, options ...interface{}) *AWSCodeCommitClient_GetFolderWithContext_Call {
return &AWSCodeCommitClient_GetFolderWithContext_Call{Call: _e.mock.On("GetFolderWithContext",
append([]interface{}{v, getFolderInput}, options...)...)}
// - fns ...func(*codecommit.Options)
func (_e *AWSCodeCommitClient_Expecter) GetFolder(context1 interface{}, getFolderInput interface{}, fns ...interface{}) *AWSCodeCommitClient_GetFolder_Call {
return &AWSCodeCommitClient_GetFolder_Call{Call: _e.mock.On("GetFolder",
append([]interface{}{context1, getFolderInput}, fns...)...)}
}
func (_c *AWSCodeCommitClient_GetFolderWithContext_Call) Run(run func(v aws.Context, getFolderInput *codecommit.GetFolderInput, options ...request.Option)) *AWSCodeCommitClient_GetFolderWithContext_Call {
func (_c *AWSCodeCommitClient_GetFolder_Call) Run(run func(context1 context.Context, getFolderInput *codecommit.GetFolderInput, fns ...func(*codecommit.Options))) *AWSCodeCommitClient_GetFolder_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 aws.Context
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(aws.Context)
arg0 = args[0].(context.Context)
}
var arg1 *codecommit.GetFolderInput
if args[1] != nil {
arg1 = args[1].(*codecommit.GetFolderInput)
}
var arg2 []request.Option
variadicArgs := make([]request.Option, len(args)-2)
var arg2 []func(*codecommit.Options)
variadicArgs := make([]func(*codecommit.Options), len(args)-2)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(request.Option)
variadicArgs[i] = a.(func(*codecommit.Options))
}
}
arg2 = variadicArgs
@@ -115,81 +115,81 @@ func (_c *AWSCodeCommitClient_GetFolderWithContext_Call) Run(run func(v aws.Cont
return _c
}
func (_c *AWSCodeCommitClient_GetFolderWithContext_Call) Return(getFolderOutput *codecommit.GetFolderOutput, err error) *AWSCodeCommitClient_GetFolderWithContext_Call {
func (_c *AWSCodeCommitClient_GetFolder_Call) Return(getFolderOutput *codecommit.GetFolderOutput, err error) *AWSCodeCommitClient_GetFolder_Call {
_c.Call.Return(getFolderOutput, err)
return _c
}
func (_c *AWSCodeCommitClient_GetFolderWithContext_Call) RunAndReturn(run func(v aws.Context, getFolderInput *codecommit.GetFolderInput, options ...request.Option) (*codecommit.GetFolderOutput, error)) *AWSCodeCommitClient_GetFolderWithContext_Call {
func (_c *AWSCodeCommitClient_GetFolder_Call) RunAndReturn(run func(context1 context.Context, getFolderInput *codecommit.GetFolderInput, fns ...func(*codecommit.Options)) (*codecommit.GetFolderOutput, error)) *AWSCodeCommitClient_GetFolder_Call {
_c.Call.Return(run)
return _c
}
// GetRepositoryWithContext provides a mock function for the type AWSCodeCommitClient
func (_mock *AWSCodeCommitClient) GetRepositoryWithContext(v aws.Context, getRepositoryInput *codecommit.GetRepositoryInput, options ...request.Option) (*codecommit.GetRepositoryOutput, error) {
// request.Option
_va := make([]interface{}, len(options))
for _i := range options {
_va[_i] = options[_i]
// GetRepository provides a mock function for the type AWSCodeCommitClient
func (_mock *AWSCodeCommitClient) GetRepository(context1 context.Context, getRepositoryInput *codecommit.GetRepositoryInput, fns ...func(*codecommit.Options)) (*codecommit.GetRepositoryOutput, error) {
// func(*codecommit.Options)
_va := make([]interface{}, len(fns))
for _i := range fns {
_va[_i] = fns[_i]
}
var _ca []interface{}
_ca = append(_ca, v, getRepositoryInput)
_ca = append(_ca, context1, getRepositoryInput)
_ca = append(_ca, _va...)
ret := _mock.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for GetRepositoryWithContext")
panic("no return value specified for GetRepository")
}
var r0 *codecommit.GetRepositoryOutput
var r1 error
if returnFunc, ok := ret.Get(0).(func(aws.Context, *codecommit.GetRepositoryInput, ...request.Option) (*codecommit.GetRepositoryOutput, error)); ok {
return returnFunc(v, getRepositoryInput, options...)
if returnFunc, ok := ret.Get(0).(func(context.Context, *codecommit.GetRepositoryInput, ...func(*codecommit.Options)) (*codecommit.GetRepositoryOutput, error)); ok {
return returnFunc(context1, getRepositoryInput, fns...)
}
if returnFunc, ok := ret.Get(0).(func(aws.Context, *codecommit.GetRepositoryInput, ...request.Option) *codecommit.GetRepositoryOutput); ok {
r0 = returnFunc(v, getRepositoryInput, options...)
if returnFunc, ok := ret.Get(0).(func(context.Context, *codecommit.GetRepositoryInput, ...func(*codecommit.Options)) *codecommit.GetRepositoryOutput); ok {
r0 = returnFunc(context1, getRepositoryInput, fns...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*codecommit.GetRepositoryOutput)
}
}
if returnFunc, ok := ret.Get(1).(func(aws.Context, *codecommit.GetRepositoryInput, ...request.Option) error); ok {
r1 = returnFunc(v, getRepositoryInput, options...)
if returnFunc, ok := ret.Get(1).(func(context.Context, *codecommit.GetRepositoryInput, ...func(*codecommit.Options)) error); ok {
r1 = returnFunc(context1, getRepositoryInput, fns...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// AWSCodeCommitClient_GetRepositoryWithContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRepositoryWithContext'
type AWSCodeCommitClient_GetRepositoryWithContext_Call struct {
// AWSCodeCommitClient_GetRepository_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRepository'
type AWSCodeCommitClient_GetRepository_Call struct {
*mock.Call
}
// GetRepositoryWithContext is a helper method to define mock.On call
// - v aws.Context
// GetRepository is a helper method to define mock.On call
// - context1 context.Context
// - getRepositoryInput *codecommit.GetRepositoryInput
// - options ...request.Option
func (_e *AWSCodeCommitClient_Expecter) GetRepositoryWithContext(v interface{}, getRepositoryInput interface{}, options ...interface{}) *AWSCodeCommitClient_GetRepositoryWithContext_Call {
return &AWSCodeCommitClient_GetRepositoryWithContext_Call{Call: _e.mock.On("GetRepositoryWithContext",
append([]interface{}{v, getRepositoryInput}, options...)...)}
// - fns ...func(*codecommit.Options)
func (_e *AWSCodeCommitClient_Expecter) GetRepository(context1 interface{}, getRepositoryInput interface{}, fns ...interface{}) *AWSCodeCommitClient_GetRepository_Call {
return &AWSCodeCommitClient_GetRepository_Call{Call: _e.mock.On("GetRepository",
append([]interface{}{context1, getRepositoryInput}, fns...)...)}
}
func (_c *AWSCodeCommitClient_GetRepositoryWithContext_Call) Run(run func(v aws.Context, getRepositoryInput *codecommit.GetRepositoryInput, options ...request.Option)) *AWSCodeCommitClient_GetRepositoryWithContext_Call {
func (_c *AWSCodeCommitClient_GetRepository_Call) Run(run func(context1 context.Context, getRepositoryInput *codecommit.GetRepositoryInput, fns ...func(*codecommit.Options))) *AWSCodeCommitClient_GetRepository_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 aws.Context
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(aws.Context)
arg0 = args[0].(context.Context)
}
var arg1 *codecommit.GetRepositoryInput
if args[1] != nil {
arg1 = args[1].(*codecommit.GetRepositoryInput)
}
var arg2 []request.Option
variadicArgs := make([]request.Option, len(args)-2)
var arg2 []func(*codecommit.Options)
variadicArgs := make([]func(*codecommit.Options), len(args)-2)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(request.Option)
variadicArgs[i] = a.(func(*codecommit.Options))
}
}
arg2 = variadicArgs
@@ -202,81 +202,81 @@ func (_c *AWSCodeCommitClient_GetRepositoryWithContext_Call) Run(run func(v aws.
return _c
}
func (_c *AWSCodeCommitClient_GetRepositoryWithContext_Call) Return(getRepositoryOutput *codecommit.GetRepositoryOutput, err error) *AWSCodeCommitClient_GetRepositoryWithContext_Call {
func (_c *AWSCodeCommitClient_GetRepository_Call) Return(getRepositoryOutput *codecommit.GetRepositoryOutput, err error) *AWSCodeCommitClient_GetRepository_Call {
_c.Call.Return(getRepositoryOutput, err)
return _c
}
func (_c *AWSCodeCommitClient_GetRepositoryWithContext_Call) RunAndReturn(run func(v aws.Context, getRepositoryInput *codecommit.GetRepositoryInput, options ...request.Option) (*codecommit.GetRepositoryOutput, error)) *AWSCodeCommitClient_GetRepositoryWithContext_Call {
func (_c *AWSCodeCommitClient_GetRepository_Call) RunAndReturn(run func(context1 context.Context, getRepositoryInput *codecommit.GetRepositoryInput, fns ...func(*codecommit.Options)) (*codecommit.GetRepositoryOutput, error)) *AWSCodeCommitClient_GetRepository_Call {
_c.Call.Return(run)
return _c
}
// ListBranchesWithContext provides a mock function for the type AWSCodeCommitClient
func (_mock *AWSCodeCommitClient) ListBranchesWithContext(v aws.Context, listBranchesInput *codecommit.ListBranchesInput, options ...request.Option) (*codecommit.ListBranchesOutput, error) {
// request.Option
_va := make([]interface{}, len(options))
for _i := range options {
_va[_i] = options[_i]
// ListBranches provides a mock function for the type AWSCodeCommitClient
func (_mock *AWSCodeCommitClient) ListBranches(context1 context.Context, listBranchesInput *codecommit.ListBranchesInput, fns ...func(*codecommit.Options)) (*codecommit.ListBranchesOutput, error) {
// func(*codecommit.Options)
_va := make([]interface{}, len(fns))
for _i := range fns {
_va[_i] = fns[_i]
}
var _ca []interface{}
_ca = append(_ca, v, listBranchesInput)
_ca = append(_ca, context1, listBranchesInput)
_ca = append(_ca, _va...)
ret := _mock.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for ListBranchesWithContext")
panic("no return value specified for ListBranches")
}
var r0 *codecommit.ListBranchesOutput
var r1 error
if returnFunc, ok := ret.Get(0).(func(aws.Context, *codecommit.ListBranchesInput, ...request.Option) (*codecommit.ListBranchesOutput, error)); ok {
return returnFunc(v, listBranchesInput, options...)
if returnFunc, ok := ret.Get(0).(func(context.Context, *codecommit.ListBranchesInput, ...func(*codecommit.Options)) (*codecommit.ListBranchesOutput, error)); ok {
return returnFunc(context1, listBranchesInput, fns...)
}
if returnFunc, ok := ret.Get(0).(func(aws.Context, *codecommit.ListBranchesInput, ...request.Option) *codecommit.ListBranchesOutput); ok {
r0 = returnFunc(v, listBranchesInput, options...)
if returnFunc, ok := ret.Get(0).(func(context.Context, *codecommit.ListBranchesInput, ...func(*codecommit.Options)) *codecommit.ListBranchesOutput); ok {
r0 = returnFunc(context1, listBranchesInput, fns...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*codecommit.ListBranchesOutput)
}
}
if returnFunc, ok := ret.Get(1).(func(aws.Context, *codecommit.ListBranchesInput, ...request.Option) error); ok {
r1 = returnFunc(v, listBranchesInput, options...)
if returnFunc, ok := ret.Get(1).(func(context.Context, *codecommit.ListBranchesInput, ...func(*codecommit.Options)) error); ok {
r1 = returnFunc(context1, listBranchesInput, fns...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// AWSCodeCommitClient_ListBranchesWithContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListBranchesWithContext'
type AWSCodeCommitClient_ListBranchesWithContext_Call struct {
// AWSCodeCommitClient_ListBranches_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListBranches'
type AWSCodeCommitClient_ListBranches_Call struct {
*mock.Call
}
// ListBranchesWithContext is a helper method to define mock.On call
// - v aws.Context
// ListBranches is a helper method to define mock.On call
// - context1 context.Context
// - listBranchesInput *codecommit.ListBranchesInput
// - options ...request.Option
func (_e *AWSCodeCommitClient_Expecter) ListBranchesWithContext(v interface{}, listBranchesInput interface{}, options ...interface{}) *AWSCodeCommitClient_ListBranchesWithContext_Call {
return &AWSCodeCommitClient_ListBranchesWithContext_Call{Call: _e.mock.On("ListBranchesWithContext",
append([]interface{}{v, listBranchesInput}, options...)...)}
// - fns ...func(*codecommit.Options)
func (_e *AWSCodeCommitClient_Expecter) ListBranches(context1 interface{}, listBranchesInput interface{}, fns ...interface{}) *AWSCodeCommitClient_ListBranches_Call {
return &AWSCodeCommitClient_ListBranches_Call{Call: _e.mock.On("ListBranches",
append([]interface{}{context1, listBranchesInput}, fns...)...)}
}
func (_c *AWSCodeCommitClient_ListBranchesWithContext_Call) Run(run func(v aws.Context, listBranchesInput *codecommit.ListBranchesInput, options ...request.Option)) *AWSCodeCommitClient_ListBranchesWithContext_Call {
func (_c *AWSCodeCommitClient_ListBranches_Call) Run(run func(context1 context.Context, listBranchesInput *codecommit.ListBranchesInput, fns ...func(*codecommit.Options))) *AWSCodeCommitClient_ListBranches_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 aws.Context
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(aws.Context)
arg0 = args[0].(context.Context)
}
var arg1 *codecommit.ListBranchesInput
if args[1] != nil {
arg1 = args[1].(*codecommit.ListBranchesInput)
}
var arg2 []request.Option
variadicArgs := make([]request.Option, len(args)-2)
var arg2 []func(*codecommit.Options)
variadicArgs := make([]func(*codecommit.Options), len(args)-2)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(request.Option)
variadicArgs[i] = a.(func(*codecommit.Options))
}
}
arg2 = variadicArgs
@@ -289,81 +289,81 @@ func (_c *AWSCodeCommitClient_ListBranchesWithContext_Call) Run(run func(v aws.C
return _c
}
func (_c *AWSCodeCommitClient_ListBranchesWithContext_Call) Return(listBranchesOutput *codecommit.ListBranchesOutput, err error) *AWSCodeCommitClient_ListBranchesWithContext_Call {
func (_c *AWSCodeCommitClient_ListBranches_Call) Return(listBranchesOutput *codecommit.ListBranchesOutput, err error) *AWSCodeCommitClient_ListBranches_Call {
_c.Call.Return(listBranchesOutput, err)
return _c
}
func (_c *AWSCodeCommitClient_ListBranchesWithContext_Call) RunAndReturn(run func(v aws.Context, listBranchesInput *codecommit.ListBranchesInput, options ...request.Option) (*codecommit.ListBranchesOutput, error)) *AWSCodeCommitClient_ListBranchesWithContext_Call {
func (_c *AWSCodeCommitClient_ListBranches_Call) RunAndReturn(run func(context1 context.Context, listBranchesInput *codecommit.ListBranchesInput, fns ...func(*codecommit.Options)) (*codecommit.ListBranchesOutput, error)) *AWSCodeCommitClient_ListBranches_Call {
_c.Call.Return(run)
return _c
}
// ListRepositoriesWithContext provides a mock function for the type AWSCodeCommitClient
func (_mock *AWSCodeCommitClient) ListRepositoriesWithContext(v aws.Context, listRepositoriesInput *codecommit.ListRepositoriesInput, options ...request.Option) (*codecommit.ListRepositoriesOutput, error) {
// request.Option
_va := make([]interface{}, len(options))
for _i := range options {
_va[_i] = options[_i]
// ListRepositories provides a mock function for the type AWSCodeCommitClient
func (_mock *AWSCodeCommitClient) ListRepositories(context1 context.Context, listRepositoriesInput *codecommit.ListRepositoriesInput, fns ...func(*codecommit.Options)) (*codecommit.ListRepositoriesOutput, error) {
// func(*codecommit.Options)
_va := make([]interface{}, len(fns))
for _i := range fns {
_va[_i] = fns[_i]
}
var _ca []interface{}
_ca = append(_ca, v, listRepositoriesInput)
_ca = append(_ca, context1, listRepositoriesInput)
_ca = append(_ca, _va...)
ret := _mock.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for ListRepositoriesWithContext")
panic("no return value specified for ListRepositories")
}
var r0 *codecommit.ListRepositoriesOutput
var r1 error
if returnFunc, ok := ret.Get(0).(func(aws.Context, *codecommit.ListRepositoriesInput, ...request.Option) (*codecommit.ListRepositoriesOutput, error)); ok {
return returnFunc(v, listRepositoriesInput, options...)
if returnFunc, ok := ret.Get(0).(func(context.Context, *codecommit.ListRepositoriesInput, ...func(*codecommit.Options)) (*codecommit.ListRepositoriesOutput, error)); ok {
return returnFunc(context1, listRepositoriesInput, fns...)
}
if returnFunc, ok := ret.Get(0).(func(aws.Context, *codecommit.ListRepositoriesInput, ...request.Option) *codecommit.ListRepositoriesOutput); ok {
r0 = returnFunc(v, listRepositoriesInput, options...)
if returnFunc, ok := ret.Get(0).(func(context.Context, *codecommit.ListRepositoriesInput, ...func(*codecommit.Options)) *codecommit.ListRepositoriesOutput); ok {
r0 = returnFunc(context1, listRepositoriesInput, fns...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*codecommit.ListRepositoriesOutput)
}
}
if returnFunc, ok := ret.Get(1).(func(aws.Context, *codecommit.ListRepositoriesInput, ...request.Option) error); ok {
r1 = returnFunc(v, listRepositoriesInput, options...)
if returnFunc, ok := ret.Get(1).(func(context.Context, *codecommit.ListRepositoriesInput, ...func(*codecommit.Options)) error); ok {
r1 = returnFunc(context1, listRepositoriesInput, fns...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// AWSCodeCommitClient_ListRepositoriesWithContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListRepositoriesWithContext'
type AWSCodeCommitClient_ListRepositoriesWithContext_Call struct {
// AWSCodeCommitClient_ListRepositories_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListRepositories'
type AWSCodeCommitClient_ListRepositories_Call struct {
*mock.Call
}
// ListRepositoriesWithContext is a helper method to define mock.On call
// - v aws.Context
// ListRepositories is a helper method to define mock.On call
// - context1 context.Context
// - listRepositoriesInput *codecommit.ListRepositoriesInput
// - options ...request.Option
func (_e *AWSCodeCommitClient_Expecter) ListRepositoriesWithContext(v interface{}, listRepositoriesInput interface{}, options ...interface{}) *AWSCodeCommitClient_ListRepositoriesWithContext_Call {
return &AWSCodeCommitClient_ListRepositoriesWithContext_Call{Call: _e.mock.On("ListRepositoriesWithContext",
append([]interface{}{v, listRepositoriesInput}, options...)...)}
// - fns ...func(*codecommit.Options)
func (_e *AWSCodeCommitClient_Expecter) ListRepositories(context1 interface{}, listRepositoriesInput interface{}, fns ...interface{}) *AWSCodeCommitClient_ListRepositories_Call {
return &AWSCodeCommitClient_ListRepositories_Call{Call: _e.mock.On("ListRepositories",
append([]interface{}{context1, listRepositoriesInput}, fns...)...)}
}
func (_c *AWSCodeCommitClient_ListRepositoriesWithContext_Call) Run(run func(v aws.Context, listRepositoriesInput *codecommit.ListRepositoriesInput, options ...request.Option)) *AWSCodeCommitClient_ListRepositoriesWithContext_Call {
func (_c *AWSCodeCommitClient_ListRepositories_Call) Run(run func(context1 context.Context, listRepositoriesInput *codecommit.ListRepositoriesInput, fns ...func(*codecommit.Options))) *AWSCodeCommitClient_ListRepositories_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 aws.Context
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(aws.Context)
arg0 = args[0].(context.Context)
}
var arg1 *codecommit.ListRepositoriesInput
if args[1] != nil {
arg1 = args[1].(*codecommit.ListRepositoriesInput)
}
var arg2 []request.Option
variadicArgs := make([]request.Option, len(args)-2)
var arg2 []func(*codecommit.Options)
variadicArgs := make([]func(*codecommit.Options), len(args)-2)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(request.Option)
variadicArgs[i] = a.(func(*codecommit.Options))
}
}
arg2 = variadicArgs
@@ -376,12 +376,12 @@ func (_c *AWSCodeCommitClient_ListRepositoriesWithContext_Call) Run(run func(v a
return _c
}
func (_c *AWSCodeCommitClient_ListRepositoriesWithContext_Call) Return(listRepositoriesOutput *codecommit.ListRepositoriesOutput, err error) *AWSCodeCommitClient_ListRepositoriesWithContext_Call {
func (_c *AWSCodeCommitClient_ListRepositories_Call) Return(listRepositoriesOutput *codecommit.ListRepositoriesOutput, err error) *AWSCodeCommitClient_ListRepositories_Call {
_c.Call.Return(listRepositoriesOutput, err)
return _c
}
func (_c *AWSCodeCommitClient_ListRepositoriesWithContext_Call) RunAndReturn(run func(v aws.Context, listRepositoriesInput *codecommit.ListRepositoriesInput, options ...request.Option) (*codecommit.ListRepositoriesOutput, error)) *AWSCodeCommitClient_ListRepositoriesWithContext_Call {
func (_c *AWSCodeCommitClient_ListRepositories_Call) RunAndReturn(run func(context1 context.Context, listRepositoriesInput *codecommit.ListRepositoriesInput, fns ...func(*codecommit.Options)) (*codecommit.ListRepositoriesOutput, error)) *AWSCodeCommitClient_ListRepositories_Call {
_c.Call.Return(run)
return _c
}

View File

@@ -5,9 +5,9 @@
package mocks
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
"context"
"github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi"
mock "github.com/stretchr/testify/mock"
)
@@ -38,71 +38,71 @@ func (_m *AWSTaggingClient) EXPECT() *AWSTaggingClient_Expecter {
return &AWSTaggingClient_Expecter{mock: &_m.Mock}
}
// GetResourcesWithContext provides a mock function for the type AWSTaggingClient
func (_mock *AWSTaggingClient) GetResourcesWithContext(v aws.Context, getResourcesInput *resourcegroupstaggingapi.GetResourcesInput, options ...request.Option) (*resourcegroupstaggingapi.GetResourcesOutput, error) {
// request.Option
_va := make([]interface{}, len(options))
for _i := range options {
_va[_i] = options[_i]
// GetResources provides a mock function for the type AWSTaggingClient
func (_mock *AWSTaggingClient) GetResources(context1 context.Context, getResourcesInput *resourcegroupstaggingapi.GetResourcesInput, fns ...func(*resourcegroupstaggingapi.Options)) (*resourcegroupstaggingapi.GetResourcesOutput, error) {
// func(*resourcegroupstaggingapi.Options)
_va := make([]interface{}, len(fns))
for _i := range fns {
_va[_i] = fns[_i]
}
var _ca []interface{}
_ca = append(_ca, v, getResourcesInput)
_ca = append(_ca, context1, getResourcesInput)
_ca = append(_ca, _va...)
ret := _mock.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for GetResourcesWithContext")
panic("no return value specified for GetResources")
}
var r0 *resourcegroupstaggingapi.GetResourcesOutput
var r1 error
if returnFunc, ok := ret.Get(0).(func(aws.Context, *resourcegroupstaggingapi.GetResourcesInput, ...request.Option) (*resourcegroupstaggingapi.GetResourcesOutput, error)); ok {
return returnFunc(v, getResourcesInput, options...)
if returnFunc, ok := ret.Get(0).(func(context.Context, *resourcegroupstaggingapi.GetResourcesInput, ...func(*resourcegroupstaggingapi.Options)) (*resourcegroupstaggingapi.GetResourcesOutput, error)); ok {
return returnFunc(context1, getResourcesInput, fns...)
}
if returnFunc, ok := ret.Get(0).(func(aws.Context, *resourcegroupstaggingapi.GetResourcesInput, ...request.Option) *resourcegroupstaggingapi.GetResourcesOutput); ok {
r0 = returnFunc(v, getResourcesInput, options...)
if returnFunc, ok := ret.Get(0).(func(context.Context, *resourcegroupstaggingapi.GetResourcesInput, ...func(*resourcegroupstaggingapi.Options)) *resourcegroupstaggingapi.GetResourcesOutput); ok {
r0 = returnFunc(context1, getResourcesInput, fns...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*resourcegroupstaggingapi.GetResourcesOutput)
}
}
if returnFunc, ok := ret.Get(1).(func(aws.Context, *resourcegroupstaggingapi.GetResourcesInput, ...request.Option) error); ok {
r1 = returnFunc(v, getResourcesInput, options...)
if returnFunc, ok := ret.Get(1).(func(context.Context, *resourcegroupstaggingapi.GetResourcesInput, ...func(*resourcegroupstaggingapi.Options)) error); ok {
r1 = returnFunc(context1, getResourcesInput, fns...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// AWSTaggingClient_GetResourcesWithContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetResourcesWithContext'
type AWSTaggingClient_GetResourcesWithContext_Call struct {
// AWSTaggingClient_GetResources_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetResources'
type AWSTaggingClient_GetResources_Call struct {
*mock.Call
}
// GetResourcesWithContext is a helper method to define mock.On call
// - v aws.Context
// GetResources is a helper method to define mock.On call
// - context1 context.Context
// - getResourcesInput *resourcegroupstaggingapi.GetResourcesInput
// - options ...request.Option
func (_e *AWSTaggingClient_Expecter) GetResourcesWithContext(v interface{}, getResourcesInput interface{}, options ...interface{}) *AWSTaggingClient_GetResourcesWithContext_Call {
return &AWSTaggingClient_GetResourcesWithContext_Call{Call: _e.mock.On("GetResourcesWithContext",
append([]interface{}{v, getResourcesInput}, options...)...)}
// - fns ...func(*resourcegroupstaggingapi.Options)
func (_e *AWSTaggingClient_Expecter) GetResources(context1 interface{}, getResourcesInput interface{}, fns ...interface{}) *AWSTaggingClient_GetResources_Call {
return &AWSTaggingClient_GetResources_Call{Call: _e.mock.On("GetResources",
append([]interface{}{context1, getResourcesInput}, fns...)...)}
}
func (_c *AWSTaggingClient_GetResourcesWithContext_Call) Run(run func(v aws.Context, getResourcesInput *resourcegroupstaggingapi.GetResourcesInput, options ...request.Option)) *AWSTaggingClient_GetResourcesWithContext_Call {
func (_c *AWSTaggingClient_GetResources_Call) Run(run func(context1 context.Context, getResourcesInput *resourcegroupstaggingapi.GetResourcesInput, fns ...func(*resourcegroupstaggingapi.Options))) *AWSTaggingClient_GetResources_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 aws.Context
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(aws.Context)
arg0 = args[0].(context.Context)
}
var arg1 *resourcegroupstaggingapi.GetResourcesInput
if args[1] != nil {
arg1 = args[1].(*resourcegroupstaggingapi.GetResourcesInput)
}
var arg2 []request.Option
variadicArgs := make([]request.Option, len(args)-2)
var arg2 []func(*resourcegroupstaggingapi.Options)
variadicArgs := make([]func(*resourcegroupstaggingapi.Options), len(args)-2)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(request.Option)
variadicArgs[i] = a.(func(*resourcegroupstaggingapi.Options))
}
}
arg2 = variadicArgs
@@ -115,12 +115,12 @@ func (_c *AWSTaggingClient_GetResourcesWithContext_Call) Run(run func(v aws.Cont
return _c
}
func (_c *AWSTaggingClient_GetResourcesWithContext_Call) Return(getResourcesOutput *resourcegroupstaggingapi.GetResourcesOutput, err error) *AWSTaggingClient_GetResourcesWithContext_Call {
func (_c *AWSTaggingClient_GetResources_Call) Return(getResourcesOutput *resourcegroupstaggingapi.GetResourcesOutput, err error) *AWSTaggingClient_GetResources_Call {
_c.Call.Return(getResourcesOutput, err)
return _c
}
func (_c *AWSTaggingClient_GetResourcesWithContext_Call) RunAndReturn(run func(v aws.Context, getResourcesInput *resourcegroupstaggingapi.GetResourcesInput, options ...request.Option) (*resourcegroupstaggingapi.GetResourcesOutput, error)) *AWSTaggingClient_GetResourcesWithContext_Call {
func (_c *AWSTaggingClient_GetResources_Call) RunAndReturn(run func(context1 context.Context, getResourcesInput *resourcegroupstaggingapi.GetResourcesInput, fns ...func(*resourcegroupstaggingapi.Options)) (*resourcegroupstaggingapi.GetResourcesOutput, error)) *AWSTaggingClient_GetResources_Call {
_c.Call.Return(run)
return _c
}

View File

@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"regexp"
"slices"
"strings"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
@@ -58,13 +59,7 @@ func matchFilter(ctx context.Context, provider SCMProviderService, repo *Reposit
}
if filter.LabelMatch != nil {
found := false
for _, label := range repo.Labels {
if filter.LabelMatch.MatchString(label) {
found = true
break
}
}
found := slices.ContainsFunc(repo.Labels, filter.LabelMatch.MatchString)
if !found {
return false, nil
}

View File

@@ -10,10 +10,6 @@ import (
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
)
func strp(s string) *string {
return &s
}
func TestFilterRepoMatch(t *testing.T) {
provider := &MockProvider{
Repos: []*Repository{
@@ -33,7 +29,7 @@ func TestFilterRepoMatch(t *testing.T) {
}
filters := []argoprojiov1alpha1.SCMProviderGeneratorFilter{
{
RepositoryMatch: strp("n|hr"),
RepositoryMatch: new("n|hr"),
},
}
repos, err := ListRepos(t.Context(), provider, filters, "")
@@ -62,7 +58,7 @@ func TestFilterLabelMatch(t *testing.T) {
}
filters := []argoprojiov1alpha1.SCMProviderGeneratorFilter{
{
LabelMatch: strp("^prod-.*$"),
LabelMatch: new("^prod-.*$"),
},
}
repos, err := ListRepos(t.Context(), provider, filters, "")
@@ -131,7 +127,7 @@ func TestFilterRepoMatchBadRegexp(t *testing.T) {
}
filters := []argoprojiov1alpha1.SCMProviderGeneratorFilter{
{
RepositoryMatch: strp("("),
RepositoryMatch: new("("),
},
}
_, err := ListRepos(t.Context(), provider, filters, "")
@@ -148,7 +144,7 @@ func TestFilterLabelMatchBadRegexp(t *testing.T) {
}
filters := []argoprojiov1alpha1.SCMProviderGeneratorFilter{
{
LabelMatch: strp("("),
LabelMatch: new("("),
},
}
_, err := ListRepos(t.Context(), provider, filters, "")
@@ -182,7 +178,7 @@ func TestFilterBranchMatch(t *testing.T) {
}
filters := []argoprojiov1alpha1.SCMProviderGeneratorFilter{
{
BranchMatch: strp("w"),
BranchMatch: new("w"),
},
}
repos, err := ListRepos(t.Context(), provider, filters, "")
@@ -213,8 +209,8 @@ func TestMultiFilterAnd(t *testing.T) {
}
filters := []argoprojiov1alpha1.SCMProviderGeneratorFilter{
{
RepositoryMatch: strp("w"),
LabelMatch: strp("^prod-.*$"),
RepositoryMatch: new("w"),
LabelMatch: new("^prod-.*$"),
},
}
repos, err := ListRepos(t.Context(), provider, filters, "")
@@ -242,10 +238,10 @@ func TestMultiFilterOr(t *testing.T) {
}
filters := []argoprojiov1alpha1.SCMProviderGeneratorFilter{
{
RepositoryMatch: strp("e"),
RepositoryMatch: new("e"),
},
{
LabelMatch: strp("^prod-.*$"),
LabelMatch: new("^prod-.*$"),
},
}
repos, err := ListRepos(t.Context(), provider, filters, "")

View File

@@ -0,0 +1,137 @@
package utils
import (
"context"
"errors"
"fmt"
"reflect"
"sync"
"unsafe"
log "github.com/sirupsen/logrus"
k8scache "k8s.io/client-go/tools/cache"
ctrlcache "sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
application "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
)
// NewCacheSyncingClient returns a client that wraps the given client and syncs the cache after each Create, Update, Patch, or Delete operation on Application objects.
func NewCacheSyncingClient(c client.Client, cache ctrlcache.Cache) client.Client {
res := &cacheSyncingClient{Client: c, storesByNs: make(map[string]k8scache.Store)}
// The k8s controller runtime's cache does not expose a way to get the underlying store, so we have to use reflection to access it.
// This is necessary to keep the cache in sync with the client operations.
field := reflect.ValueOf(cache).Elem().FieldByName("namespaceToCache")
if field.Kind() == reflect.Map {
namespaceToCache := *(*map[string]ctrlcache.Cache)(unsafe.Pointer(field.UnsafeAddr()))
res.getNSCache = func(_ context.Context, obj client.Object) (ctrlcache.Cache, error) {
res, ok := namespaceToCache[obj.GetNamespace()]
if !ok {
return nil, fmt.Errorf("cache for namespace %s not found", obj.GetNamespace())
}
return res, nil
}
} else {
res.getNSCache = func(_ context.Context, _ client.Object) (ctrlcache.Cache, error) {
return cache, nil
}
}
return res
}
type cacheSyncingClient struct {
client.Client
getNSCache func(ctx context.Context, obj client.Object) (ctrlcache.Cache, error)
storesByNs map[string]k8scache.Store
storesByNsLock sync.RWMutex
}
func (c *cacheSyncingClient) getStore(ctx context.Context, obj client.Object) (k8scache.Store, error) {
c.storesByNsLock.RLock()
store, ok := c.storesByNs[obj.GetNamespace()]
c.storesByNsLock.RUnlock()
if ok {
return store, nil
}
store, err := c.retrieveStore(ctx, obj)
if err != nil {
return nil, err
}
c.storesByNsLock.Lock()
c.storesByNs[obj.GetNamespace()] = store
c.storesByNsLock.Unlock()
return store, nil
}
func (c *cacheSyncingClient) retrieveStore(ctx context.Context, obj client.Object) (k8scache.Store, error) {
nsCache, err := c.getNSCache(ctx, obj)
if err != nil {
return nil, fmt.Errorf("failed to get namespace cache: %w", err)
}
informer, err := nsCache.GetInformerForKind(ctx, application.ApplicationSchemaGroupVersionKind)
if err != nil {
return nil, fmt.Errorf("failed to get informer: %w", err)
}
indexInformer, ok := informer.(k8scache.SharedIndexInformer)
if !ok {
return nil, errors.New("informer is not a SharedIndexInformer")
}
return indexInformer.GetStore(), nil
}
func (c *cacheSyncingClient) execAndSyncCache(ctx context.Context, op func() error, obj client.Object, deleteObj bool) error {
// execute the operation first and only sync cache if it succeeds
if err := op(); err != nil {
return err
}
// sync cache for applications only
if _, ok := obj.(*application.Application); !ok {
return nil
}
logger := log.WithField("namespace", obj.GetNamespace()).WithField("name", obj.GetName())
store, err := c.getStore(ctx, obj)
if err != nil {
logger.Errorf("failed to get cache store: %v", err)
} else {
if deleteObj {
err = store.Delete(obj)
} else {
err = store.Update(obj)
}
}
if err != nil {
logger.Errorf("failed to sync cache for object: %v", err)
}
return nil
}
func (c *cacheSyncingClient) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error {
return c.execAndSyncCache(ctx, func() error {
return c.Client.Create(ctx, obj, opts...)
}, obj, false)
}
func (c *cacheSyncingClient) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error {
return c.execAndSyncCache(ctx, func() error {
return c.Client.Update(ctx, obj, opts...)
}, obj, false)
}
func (c *cacheSyncingClient) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error {
return c.execAndSyncCache(ctx, func() error {
return c.Client.Patch(ctx, obj, patch, opts...)
}, obj, false)
}
func (c *cacheSyncingClient) Delete(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error {
return c.execAndSyncCache(ctx, func() error {
return c.Client.Delete(ctx, obj, opts...)
}, obj, true)
}

View File

@@ -0,0 +1,111 @@
package utils
import (
"context"
"testing"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
k8scache "k8s.io/client-go/tools/cache"
ctrlcache "sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
application "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
)
type fakeMultiNamespaceCache struct {
//nolint:unused
namespaceToCache map[string]ctrlcache.Cache
ctrlcache.Cache
k8scache.SharedIndexInformer
Store k8scache.Store
}
func (f *fakeMultiNamespaceCache) GetInformerForKind(_ context.Context, _ schema.GroupVersionKind, _ ...ctrlcache.InformerGetOption) (ctrlcache.Informer, error) {
return f, nil
}
func (f *fakeMultiNamespaceCache) GetStore() k8scache.Store {
return f.Store
}
func newClient(objs ...client.Object) (*cacheSyncingClient, k8scache.Store, error) {
scheme := runtime.NewScheme()
if err := application.AddToScheme(scheme); err != nil {
return nil, nil, err
}
store := k8scache.NewStore(func(obj any) (string, error) {
return obj.(client.Object).GetName(), nil
})
for _, obj := range objs {
if err := store.Add(obj); err != nil {
return nil, nil, err
}
}
c := &cacheSyncingClient{
Client: fake.NewClientBuilder().WithScheme(scheme).WithObjects(objs...).Build(),
storesByNs: map[string]k8scache.Store{},
getNSCache: func(_ context.Context, _ client.Object) (ctrlcache.Cache, error) {
return &fakeMultiNamespaceCache{Store: store}, nil
},
}
return c, store, nil
}
func TestCreateSyncsCache(t *testing.T) {
c, store, err := newClient()
require.NoError(t, err)
app := &application.Application{
ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "argocd"},
}
require.NoError(t, c.Create(context.Background(), app))
require.Contains(t, store.List(), app)
}
func TestUpdateSyncsCache(t *testing.T) {
app := &application.Application{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "argocd",
Labels: map[string]string{"foo": "bar"},
},
}
c, store, err := newClient(app)
require.NoError(t, err)
updatedApp := app.DeepCopy()
updatedApp.Labels["foo"] = "bar-UPDATED"
require.NoError(t, c.Update(context.Background(), updatedApp))
updated, _, err := store.GetByKey("test")
require.NoError(t, err)
require.Equal(t, "bar-UPDATED", updated.(*application.Application).Labels["foo"])
}
func TestDeleteSyncsCache(t *testing.T) {
app := &application.Application{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "argocd",
Labels: map[string]string{"foo": "bar"},
},
}
c, store, err := newClient(app)
require.NoError(t, err)
require.NoError(t, c.Delete(context.Background(), app))
require.Empty(t, store.List())
}
func TestNewClientDoesNotCrashWithMultiNamespaceCache(_ *testing.T) {
_ = NewCacheSyncingClient(nil, &fakeMultiNamespaceCache{})
}

View File

@@ -216,7 +216,6 @@ spec:
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
foundApp := v1alpha1.Application{TypeMeta: appMeta}

View File

@@ -2,6 +2,7 @@ package utils
import (
"fmt"
"slices"
"sort"
"strconv"
"strings"
@@ -207,12 +208,7 @@ type Requirement struct {
}
func (r *Requirement) hasValue(value string) bool {
for i := range r.strValues {
if r.strValues[i] == value {
return true
}
}
return false
return slices.Contains(r.strValues, value)
}
func (r *Requirement) Matches(ls labels.Labels) bool {

View File

@@ -90,7 +90,7 @@ func ConvertYAMLToJSON(str string) (string, error) {
// This function is in charge of searching all String fields of the object recursively and apply templating
// thanks to https://gist.github.com/randallmlough/1fd78ec8a1034916ca52281e3b886dc7
func (r *Render) deeplyReplace(destination, original reflect.Value, replaceMap map[string]any, useGoTemplate bool, goTemplateOptions []string) error {
func (r *Render) deeplyReplaceWithFilter(destination, original reflect.Value, replaceMap map[string]any, useGoTemplate bool, goTemplateOptions []string, filter func(destination, original, parent reflect.Value, field reflect.StructField) (bool, error)) error {
switch original.Kind() {
// The first cases handle nested structures and translate them recursively
// If it is a pointer we need to unwrap and call once again
@@ -110,7 +110,7 @@ func (r *Render) deeplyReplace(destination, original reflect.Value, replaceMap m
copyUnexported(destination, original)
}
// Unwrap the newly created pointer
if err := r.deeplyReplace(destination.Elem(), originalValue, replaceMap, useGoTemplate, goTemplateOptions); err != nil {
if err := r.deeplyReplaceWithFilter(destination.Elem(), originalValue, replaceMap, useGoTemplate, goTemplateOptions, filter); err != nil {
// Not wrapping the error, since this is a recursive function. Avoids excessively long error messages.
return err
}
@@ -131,7 +131,7 @@ func (r *Render) deeplyReplace(destination, original reflect.Value, replaceMap m
reflectValue := reflect.New(reflectType)
copyValue := reflectValue.Elem()
if err := r.deeplyReplace(copyValue, originalValue, replaceMap, useGoTemplate, goTemplateOptions); err != nil {
if err := r.deeplyReplaceWithFilter(copyValue, originalValue, replaceMap, useGoTemplate, goTemplateOptions, filter); err != nil {
// Not wrapping the error, since this is a recursive function. Avoids excessively long error messages.
return err
}
@@ -142,6 +142,16 @@ func (r *Render) deeplyReplace(destination, original reflect.Value, replaceMap m
case reflect.Struct:
for i := 0; i < original.NumField(); i++ {
currentType := fmt.Sprintf("%s.%s", original.Type().Field(i).Name, original.Type().PkgPath())
if filter != nil {
matched, filterErr := filter(destination.Field(i), original.Field(i), original,
original.Type().Field(i))
if matched {
if filterErr != nil {
return filterErr
}
continue
}
}
// specific case time
if currentType == "time.Time" {
destination.Field(i).Set(original.Field(i))
@@ -158,7 +168,7 @@ func (r *Render) deeplyReplace(destination, original reflect.Value, replaceMap m
}
jsonOriginal := reflect.ValueOf(&unmarshaled)
jsonCopy := reflect.New(jsonOriginal.Type()).Elem()
err = r.deeplyReplace(jsonCopy, jsonOriginal, replaceMap, useGoTemplate, goTemplateOptions)
err = r.deeplyReplaceWithFilter(jsonCopy, jsonOriginal, replaceMap, useGoTemplate, goTemplateOptions, filter)
if err != nil {
return fmt.Errorf("failed to deeply replace JSON field contents: %w", err)
}
@@ -168,7 +178,7 @@ func (r *Render) deeplyReplace(destination, original reflect.Value, replaceMap m
return fmt.Errorf("failed to marshal templated JSON field: %w", err)
}
destination.Field(i).Set(reflect.ValueOf(data))
} else if err := r.deeplyReplace(destination.Field(i), original.Field(i), replaceMap, useGoTemplate, goTemplateOptions); err != nil {
} else if err := r.deeplyReplaceWithFilter(destination.Field(i), original.Field(i), replaceMap, useGoTemplate, goTemplateOptions, filter); err != nil {
// Not wrapping the error, since this is a recursive function. Avoids excessively long error messages.
return err
}
@@ -183,7 +193,7 @@ func (r *Render) deeplyReplace(destination, original reflect.Value, replaceMap m
}
for i := 0; i < original.Len(); i++ {
if err := r.deeplyReplace(destination.Index(i), original.Index(i), replaceMap, useGoTemplate, goTemplateOptions); err != nil {
if err := r.deeplyReplaceWithFilter(destination.Index(i), original.Index(i), replaceMap, useGoTemplate, goTemplateOptions, filter); err != nil {
// Not wrapping the error, since this is a recursive function. Avoids excessively long error messages.
return err
}
@@ -204,7 +214,7 @@ func (r *Render) deeplyReplace(destination, original reflect.Value, replaceMap m
// New gives us a pointer, but again we want the value
copyValue := reflect.New(originalValue.Type()).Elem()
if err := r.deeplyReplace(copyValue, originalValue, replaceMap, useGoTemplate, goTemplateOptions); err != nil {
if err := r.deeplyReplaceWithFilter(copyValue, originalValue, replaceMap, useGoTemplate, goTemplateOptions, filter); err != nil {
// Not wrapping the error, since this is a recursive function. Avoids excessively long error messages.
return err
}
@@ -249,6 +259,10 @@ func (r *Render) deeplyReplace(destination, original reflect.Value, replaceMap m
return nil
}
func (r *Render) deeplyReplace(destination, original reflect.Value, replaceMap map[string]any, useGoTemplate bool, goTemplateOptions []string) error {
return r.deeplyReplaceWithFilter(destination, original, replaceMap, useGoTemplate, goTemplateOptions, nil)
}
// isNillable returns true if the value is something which may be set to nil. This function is meant to guard against a
// panic from calling IsNil on a non-pointer type.
func isNillable(v reflect.Value) bool {
@@ -290,6 +304,27 @@ func (r *Render) RenderTemplateParams(tmpl *argoappsv1.Application, syncPolicy *
return replacedTmpl, nil
}
// Generator types that have Value field
var filteredGeneratorTypes = getFilteredGeneratorTypes()
// find generator types that have Values field
func getFilteredGeneratorTypes() map[string]bool {
result := map[string]bool{}
t := reflect.TypeFor[argoappsv1.ApplicationSetGenerator]()
for field := range t.Fields() {
genPtrType := field.Type
if genPtrType.Kind() == reflect.Ptr && strings.HasSuffix(genPtrType.String(), "Generator") {
genType := genPtrType.Elem()
for field := range genType.Fields() {
if field.Name == "Values" && field.Type.String() == "map[string]string" {
result[genType.Name()] = true
}
}
}
}
return result
}
func (r *Render) RenderGeneratorParams(gen *argoappsv1.ApplicationSetGenerator, params map[string]any, useGoTemplate bool, goTemplateOptions []string) (*argoappsv1.ApplicationSetGenerator, error) {
if gen == nil {
return nil, errors.New("generator is empty")
@@ -302,7 +337,17 @@ func (r *Render) RenderGeneratorParams(gen *argoappsv1.ApplicationSetGenerator,
original := reflect.ValueOf(gen)
destination := reflect.New(original.Type()).Elem()
if err := r.deeplyReplace(destination, original, params, useGoTemplate, goTemplateOptions); err != nil {
filter := func(destination, original, parent reflect.Value, field reflect.StructField) (bool, error) {
if field.Name == "Values" && field.Type.String() == "map[string]string" && filteredGeneratorTypes[parent.Type().Name()] {
if !destination.CanSet() {
return false, fmt.Errorf("cannot copy %s.Values, this cannot happen", parent.Type().Name())
}
destination.Set(original)
return true, nil
}
return false, nil
}
if err := r.deeplyReplaceWithFilter(destination, original, params, useGoTemplate, goTemplateOptions, filter); err != nil {
return nil, fmt.Errorf("failed to replace parameters in generator: %w", err)
}
@@ -388,8 +433,7 @@ func invalidGenerators(applicationSetInfo *argoappsv1.ApplicationSet) (bool, map
for index, generator := range applicationSetInfo.Spec.Generators {
v := reflect.Indirect(reflect.ValueOf(generator))
found := false
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
for _, field := range v.Fields() {
if !field.CanInterface() {
continue
}

View File

@@ -5,6 +5,7 @@ import (
"encoding/json"
"os"
"path"
"strings"
"testing"
"time"
@@ -1390,3 +1391,12 @@ WkBKOclmOV2xlTVuPw==
})
}
}
func Test_getFilteredGeneratorTypes(t *testing.T) {
generators := getFilteredGeneratorTypes()
assert.Less(t, 1, len(generators))
for name, val := range generators {
assert.True(t, val)
assert.True(t, strings.HasSuffix(name, "Generator"))
}
}

View File

@@ -107,10 +107,8 @@ func NewWebhookHandler(webhookParallelism int, argocdSettingsMgr *argosettings.S
func (h *WebhookHandler) startWorkerPool(webhookParallelism int) {
compLog := log.WithField("component", "applicationset-webhook")
for i := 0; i < webhookParallelism; i++ {
h.Add(1)
go func() {
defer h.Done()
for range webhookParallelism {
h.Go(func() {
for {
payload, ok := <-h.queue
if !ok {
@@ -118,7 +116,7 @@ func (h *WebhookHandler) startWorkerPool(webhookParallelism int) {
}
guard.RecoverAndLog(func() { h.HandleEvent(payload) }, compLog, panicMsgAppSet)
}
}()
})
}
}

View File

@@ -233,7 +233,7 @@ func TestWebhookHandler(t *testing.T) {
h, err := NewWebhookHandler(webhookParallelism, set, fc, mockGenerators())
require.NoError(t, err)
req := httptest.NewRequest(http.MethodPost, "/api/webhook", http.NoBody)
req := httptest.NewRequestWithContext(t.Context(), http.MethodPost, "/api/webhook", http.NoBody)
req.Header.Set(test.headerKey, test.headerValue)
eventJSON, err := os.ReadFile(filepath.Join("testdata", test.payloadFile))
require.NoError(t, err)
@@ -609,7 +609,7 @@ func fakeAppWithMatrixAndNestedGitGenerator(name, namespace, repo string) *v1alp
},
{
Matrix: &apiextensionsv1.JSON{
Raw: []byte(fmt.Sprintf(`{
Raw: fmt.Appendf(nil, `{
"Generators": [
{
"List": {
@@ -626,7 +626,7 @@ func fakeAppWithMatrixAndNestedGitGenerator(name, namespace, repo string) *v1alp
}
}
]
}`, repo)),
}`, repo),
},
},
},
@@ -707,7 +707,7 @@ func fakeAppWithMergeAndNestedGitGenerator(name, namespace, repo string) *v1alph
},
{
Merge: &apiextensionsv1.JSON{
Raw: []byte(fmt.Sprintf(`{
Raw: fmt.Appendf(nil, `{
"MergeKeys": ["server"],
"Generators": [
{
@@ -719,7 +719,7 @@ func fakeAppWithMergeAndNestedGitGenerator(name, namespace, repo string) *v1alph
}
}
]
}`, repo)),
}`, repo),
},
},
},

82
assets/swagger.json generated
View File

@@ -4385,6 +4385,69 @@
}
}
},
"/api/v1/stream/applicationsets": {
"get": {
"tags": [
"ApplicationSetService"
],
"operationId": "ApplicationSetService_Watch",
"parameters": [
{
"type": "string",
"name": "name",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "multi",
"name": "projects",
"in": "query"
},
{
"type": "string",
"name": "selector",
"in": "query"
},
{
"type": "string",
"name": "appSetNamespace",
"in": "query"
},
{
"type": "string",
"description": "when specified with a watch call, shows changes that occur after that particular version of a resource.",
"name": "resourceVersion",
"in": "query"
}
],
"responses": {
"200": {
"description": "A successful response.(streaming responses)",
"schema": {
"type": "object",
"title": "Stream result of v1alpha1ApplicationSetWatchEvent",
"properties": {
"error": {
"$ref": "#/definitions/runtimeStreamError"
},
"result": {
"$ref": "#/definitions/v1alpha1ApplicationSetWatchEvent"
}
}
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/runtimeError"
}
}
}
}
},
"/api/v1/write-repocreds": {
"get": {
"tags": [
@@ -7459,6 +7522,19 @@
}
}
},
"v1alpha1ApplicationSetWatchEvent": {
"description": "ApplicationSetWatchEvent contains information about application change.",
"type": "object",
"properties": {
"applicationSet": {
"$ref": "#/definitions/v1alpha1ApplicationSet"
},
"type": {
"type": "string",
"title": "Type represents the Kubernetes watch event type. The protobuf tag uses\ncasttype to ensure the generated Go code keeps this field as\nwatch.EventType (a strong Go type) instead of falling back to a plain string"
}
}
},
"v1alpha1ApplicationSource": {
"type": "object",
"title": "ApplicationSource contains all required information about the source of an application",
@@ -7695,11 +7771,11 @@
},
"namePrefix": {
"type": "string",
"title": "NamePrefix is a prefix appended to resources for Kustomize apps"
"title": "NamePrefix overrides the namePrefix in the kustomization.yaml for Kustomize apps"
},
"nameSuffix": {
"type": "string",
"title": "NameSuffix is a suffix appended to resources for Kustomize apps"
"title": "NameSuffix overrides the nameSuffix in the kustomization.yaml for Kustomize apps"
},
"namespace": {
"type": "string",
@@ -9756,7 +9832,7 @@
"type": "object",
"properties": {
"diff": {
"description": "Diff contains the JSON patch representing the difference between the live and target resource.\nDeprecated: Use NormalizedLiveState and PredictedLiveState instead to compute differences.",
"description": "Diff contains the JSON patch representing the difference between the live and target resource.\n\nDeprecated: Use NormalizedLiveState and PredictedLiveState instead to compute differences.",
"type": "string"
},
"group": {

View File

@@ -41,8 +41,6 @@ import (
)
const (
// CLIName is the name of the CLI
cliName = common.ApplicationController
// Default time in seconds for application resync period
defaultAppResyncPeriod = 120
// Default time in seconds for application resync period jitter
@@ -99,7 +97,7 @@ func NewCommand() *cobra.Command {
hydratorEnabled bool
)
command := cobra.Command{
Use: cliName,
Use: common.CommandApplicationController,
Short: "Run ArgoCD Application Controller",
Long: "ArgoCD application controller is a Kubernetes controller that continuously monitors running applications and compares the current, live state against the desired target state (as specified in the repo). This command runs Application Controller in the foreground. It can be configured by following options.",
DisableAutoGenTag: true,

View File

@@ -49,10 +49,6 @@ import (
var gitSubmoduleEnabled = env.ParseBoolFromEnv(common.EnvGitSubmoduleEnabled, true)
const (
cliName = common.ApplicationSetController
)
func NewCommand() *cobra.Command {
var (
clientConfig clientcmd.ClientConfig
@@ -82,12 +78,13 @@ func NewCommand() *cobra.Command {
webhookParallelism int
tokenRefStrictMode bool
maxResourcesStatusCount int
cacheSyncPeriod time.Duration
)
scheme := runtime.NewScheme()
_ = clientgoscheme.AddToScheme(scheme)
_ = appv1alpha1.AddToScheme(scheme)
command := cobra.Command{
Use: cliName,
Use: common.CommandApplicationSetController,
Short: "Starts Argo CD ApplicationSet controller",
DisableAutoGenTag: true,
RunE: func(c *cobra.Command, _ []string) error {
@@ -143,13 +140,11 @@ func NewCommand() *cobra.Command {
os.Exit(1)
}
var cacheOpt ctrlcache.Options
cacheOpt := ctrlcache.Options{SyncPeriod: &cacheSyncPeriod}
if watchedNamespace != "" {
cacheOpt = ctrlcache.Options{
DefaultNamespaces: map[string]ctrlcache.Config{
watchedNamespace: {},
},
cacheOpt.DefaultNamespaces = map[string]ctrlcache.Config{
watchedNamespace: {},
}
}
@@ -245,7 +240,7 @@ func NewCommand() *cobra.Command {
if err = (&controllers.ApplicationSetReconciler{
Generators: topLevelGenerators,
Client: mgr.GetClient(),
Client: utils.NewCacheSyncingClient(mgr.GetClient(), mgr.GetCache()),
Scheme: mgr.GetScheme(),
Recorder: mgr.GetEventRecorderFor("applicationset-controller"),
Renderer: &utils.Render{},
@@ -306,7 +301,8 @@ func NewCommand() *cobra.Command {
command.Flags().IntVar(&webhookParallelism, "webhook-parallelism-limit", env.ParseNumFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_WEBHOOK_PARALLELISM_LIMIT", 50, 1, 1000), "Number of webhook requests processed concurrently")
command.Flags().StringSliceVar(&metricsAplicationsetLabels, "metrics-applicationset-labels", []string{}, "List of Application labels that will be added to the argocd_applicationset_labels metric")
command.Flags().BoolVar(&enableGitHubAPIMetrics, "enable-github-api-metrics", env.ParseBoolFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_GITHUB_API_METRICS", false), "Enable GitHub API metrics for generators that use the GitHub API")
command.Flags().IntVar(&maxResourcesStatusCount, "max-resources-status-count", env.ParseNumFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_MAX_RESOURCES_STATUS_COUNT", 0, 0, math.MaxInt), "Max number of resources stored in appset status.")
command.Flags().IntVar(&maxResourcesStatusCount, "max-resources-status-count", env.ParseNumFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_MAX_RESOURCES_STATUS_COUNT", 5000, 0, math.MaxInt), "Max number of resources stored in appset status.")
command.Flags().DurationVar(&cacheSyncPeriod, "cache-sync-period", env.ParseDurationFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_CACHE_SYNC_PERIOD", time.Hour*10, 0, time.Hour*24), "Period at which the manager client cache is forcefully resynced with the Kubernetes API server. 0 disables periodic resync.")
return &command
}

View File

@@ -18,11 +18,6 @@ import (
traceutil "github.com/argoproj/argo-cd/v3/util/trace"
)
const (
// CLIName is the name of the CLI
cliName = "argocd-cmp-server"
)
func NewCommand() *cobra.Command {
var (
configFilePath string
@@ -32,7 +27,7 @@ func NewCommand() *cobra.Command {
otlpAttrs []string
)
command := cobra.Command{
Use: cliName,
Use: common.CommandCMPServer,
Short: "Run ArgoCD ConfigManagementPlugin Server",
Long: "ArgoCD ConfigManagementPlugin Server is an internal service which runs as sidecar container in reposerver deployment. The following configuration options are available:",
DisableAutoGenTag: true,

View File

@@ -35,7 +35,7 @@ func NewCommand() *cobra.Command {
metricsHost string
)
command := &cobra.Command{
Use: "argocd-commit-server",
Use: common.CommandCommitServer,
Short: "Run Argo CD Commit Server",
Long: "Argo CD Commit Server is an internal service which commits and pushes hydrated manifests to git. This command runs Commit Server in the foreground.",
RunE: func(cmd *cobra.Command, _ []string) error {
@@ -91,13 +91,11 @@ func NewCommand() *cobra.Command {
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
wg.Go(func() {
s := <-sigCh
log.Printf("got signal %v, attempting graceful shutdown", s)
grpc.GracefulStop()
wg.Done()
}()
})
log.Println("starting grpc server")
err = grpc.Serve(listener)

View File

@@ -25,13 +25,9 @@ import (
"github.com/argoproj/argo-cd/v3/util/tls"
)
const (
cliName = "argocd-dex"
)
func NewCommand() *cobra.Command {
command := &cobra.Command{
Use: cliName,
Use: common.CommandDex,
Short: "argocd-dex tools used by Argo CD",
Long: "argocd-dex has internal utility tools used by Argo CD",
DisableAutoGenTag: true,

View File

@@ -9,20 +9,16 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"github.com/argoproj/argo-cd/v3/common"
"github.com/argoproj/argo-cd/v3/util/askpass"
"github.com/argoproj/argo-cd/v3/util/errors"
grpc_util "github.com/argoproj/argo-cd/v3/util/grpc"
utilio "github.com/argoproj/argo-cd/v3/util/io"
)
const (
// cliName is the name of the CLI
cliName = "argocd-git-ask-pass"
)
func NewCommand() *cobra.Command {
command := cobra.Command{
Use: cliName,
Use: common.CommandGitAskPass,
Short: "Argo CD git credential helper",
DisableAutoGenTag: true,
Run: func(c *cobra.Command, _ []string) {

View File

@@ -2,15 +2,13 @@ package commands
import (
"github.com/spf13/cobra"
)
const (
cliName = "argocd-k8s-auth"
"github.com/argoproj/argo-cd/v3/common"
)
func NewCommand() *cobra.Command {
command := &cobra.Command{
Use: cliName,
Use: common.CommandK8sAuth,
Short: "argocd-k8s-auth a set of commands to generate k8s auth token",
DisableAutoGenTag: true,
Run: func(c *cobra.Command, args []string) {

View File

@@ -6,12 +6,14 @@ import (
"encoding/json"
"fmt"
"os"
"strconv"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/sts"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials/stscreds"
"github.com/aws/aws-sdk-go-v2/service/sts"
smithyhttp "github.com/aws/smithy-go/transport/http"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clientauthv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
@@ -58,13 +60,13 @@ func newAWSCommand() *cobra.Command {
return command
}
type getSignedRequestFunc func(clusterName, roleARN string, profile string) (string, error)
type getSignedRequestFunc func(ctx context.Context, clusterName, roleARN string, profile string) (string, error)
func getSignedRequestWithRetry(ctx context.Context, timeout, interval time.Duration, clusterName, roleARN string, profile string, fn getSignedRequestFunc) (string, error) {
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
for {
signed, err := fn(clusterName, roleARN, profile)
signed, err := fn(ctx, clusterName, roleARN, profile)
if err == nil {
return signed, nil
}
@@ -76,25 +78,53 @@ func getSignedRequestWithRetry(ctx context.Context, timeout, interval time.Durat
}
}
func getSignedRequest(clusterName, roleARN string, profile string) (string, error) {
sess, err := session.NewSessionWithOptions(session.Options{
Profile: profile,
})
func getSignedRequest(ctx context.Context, clusterName, roleARN string, profile string) (string, error) {
cfg, err := loadAWSConfig(ctx, profile)
if err != nil {
return "", fmt.Errorf("error creating new AWS session: %w", err)
return "", err
}
stsAPI := sts.New(sess)
return getSignedRequestWithConfig(ctx, clusterName, roleARN, cfg)
}
func loadAWSConfig(ctx context.Context, profile string) (aws.Config, error) {
var opts []func(*config.LoadOptions) error
if profile != "" {
opts = append(opts, config.WithSharedConfigProfile(profile))
}
cfg, err := config.LoadDefaultConfig(ctx, opts...)
if err != nil {
return aws.Config{}, fmt.Errorf("error loading AWS configuration: %w", err)
}
return cfg, nil
}
// getSignedRequestWithConfig presigns GetCallerIdentity using the given config. Used by getSignedRequest and by tests
// that inject a config with static credentials to exercise the roleARN path without real AWS credentials.
func getSignedRequestWithConfig(ctx context.Context, clusterName, roleARN string, cfg aws.Config) (string, error) {
// Use PresignOptions.ClientOptions + SetHeaderValue (same as aws-iam-authenticator) so the
// canonical request matches what EKS sends when validating. Build middleware can produce
// a different canonical form and thus an invalid signature for EKS.
// See kubernetes-sigs/aws-iam-authenticator pkg/token/token.go GetWithSTS().
client := sts.NewFromConfig(cfg)
if roleARN != "" {
creds := stscreds.NewCredentials(sess, roleARN)
stsAPI = sts.New(sess, &aws.Config{Credentials: creds})
appCreds := stscreds.NewAssumeRoleProvider(client, roleARN)
cfg.Credentials = aws.NewCredentialsCache(appCreds)
client = sts.NewFromConfig(cfg)
}
request, _ := stsAPI.GetCallerIdentityRequest(&sts.GetCallerIdentityInput{})
request.HTTPRequest.Header.Add(clusterIDHeader, clusterName)
signed, err := request.Presign(requestPresignParam)
presignClient := sts.NewPresignClient(client)
presigned, err := presignClient.PresignGetCallerIdentity(ctx, &sts.GetCallerIdentityInput{},
func(presignOptions *sts.PresignOptions) {
presignOptions.ClientOptions = append(presignOptions.ClientOptions, func(stsOptions *sts.Options) {
stsOptions.APIOptions = append(stsOptions.APIOptions,
smithyhttp.SetHeaderValue(clusterIDHeader, clusterName),
smithyhttp.SetHeaderValue("X-Amz-Expires", strconv.Itoa(requestPresignParam)))
})
})
if err != nil {
return "", fmt.Errorf("error presigning AWS request: %w", err)
}
return signed, nil
return presigned.URL, nil
}
func formatJSON(token string, expiration time.Time) string {

View File

@@ -1,14 +1,60 @@
package commands
import (
"context"
"errors"
"testing"
"time"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGetSignedRequest(t *testing.T) {
t.Parallel()
t.Run("returns error when context is cancelled", func(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithCancel(context.Background())
cancel()
url, err := getSignedRequest(ctx, "my-cluster", "", "")
require.ErrorIs(t, err, context.Canceled)
assert.Empty(t, url)
})
t.Run("returns error for non-existent profile", func(t *testing.T) {
t.Parallel()
ctx := context.Background()
profile := "argocd-k8s-auth-test-nonexistent-profile-12345"
url, err := getSignedRequest(ctx, "my-cluster", "", profile)
require.Error(t, err)
assert.Empty(t, url)
assert.Contains(t, err.Error(), "configuration", "error should mention configuration load failed")
})
t.Run("returns error when roleARN is provided and assume role fails", func(t *testing.T) {
t.Parallel()
ctx := context.Background()
cfg, err := config.LoadDefaultConfig(ctx,
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider("test", "test", "")),
config.WithRegion("us-east-1"),
)
require.NoError(t, err)
url, err := getSignedRequestWithConfig(ctx, "my-cluster", "arn:aws:iam::123456789012:role/NonExistentRole", cfg)
require.Error(t, err)
assert.Empty(t, url)
assert.Contains(t, err.Error(), "presigning", "error should mention presigning failed when assume role is used")
})
}
func TestGetSignedRequestWithRetry(t *testing.T) {
t.Parallel()
@@ -72,7 +118,7 @@ type signedRequestMock struct {
returnFunc func(m *signedRequestMock) (string, error)
}
func (m *signedRequestMock) getSignedRequestMock(_, _ string, _ string) (string, error) {
func (m *signedRequestMock) getSignedRequestMock(_ context.Context, _, _ string, _ string) (string, error) {
m.getSignedRequestCalls++
return m.returnFunc(m)
}

View File

@@ -3,6 +3,7 @@ package commands
import (
"context"
"fmt"
"math"
"net/http"
"os"
"os/signal"
@@ -52,7 +53,7 @@ func NewCommand() *cobra.Command {
selfServiceNotificationEnabled bool
)
command := cobra.Command{
Use: "controller",
Use: common.CommandNotifications,
Short: "Starts Argo CD Notifications controller",
RunE: func(_ *cobra.Command, _ []string) error {
ctx, cancel := context.WithCancel(context.Background())
@@ -126,7 +127,7 @@ func NewCommand() *cobra.Command {
tlsConfig.Certificates = pool
}
repoClientset := apiclient.NewRepoServerClientset(argocdRepoServer, 5, tlsConfig)
argocdService, err := service.NewArgoCDService(k8sClient, namespace, repoClientset)
argocdService, err := service.NewArgoCDService(k8sClient, dynamicClient, namespace, repoClientset)
if err != nil {
return fmt.Errorf("failed to initialize Argo CD service: %w", err)
}
@@ -150,13 +151,11 @@ func NewCommand() *cobra.Command {
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
wg.Go(func() {
s := <-sigCh
log.Printf("got signal %v, attempting graceful shutdown", s)
cancel()
}()
})
go ctrl.Run(ctx, processorsCount)
<-ctx.Done()
@@ -164,7 +163,7 @@ func NewCommand() *cobra.Command {
},
}
clientConfig = cli.AddKubectlFlagsToCmd(&command)
command.Flags().IntVar(&processorsCount, "processors-count", 1, "Processors count.")
command.Flags().IntVar(&processorsCount, "processors-count", env.ParseNumFromEnv("ARGOCD_NOTIFICATION_CONTROLLER_PROCESSORS_COUNT", 1, 1, math.MaxInt32), "Processors count.")
command.Flags().StringVar(&appLabelSelector, "app-label-selector", "", "App label selector.")
command.Flags().StringVar(&logLevel, "loglevel", env.StringFromEnv("ARGOCD_NOTIFICATIONS_CONTROLLER_LOGLEVEL", "info"), "Set the logging level. One of: debug|info|warn|error")
command.Flags().StringVar(&logFormat, "logformat", env.StringFromEnv("ARGOCD_NOTIFICATIONS_CONTROLLER_LOGFORMAT", "json"), "Set the logging format. One of: json|text")

View File

@@ -0,0 +1,28 @@
package commands
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewCommandProcessorsCountDefault(t *testing.T) {
t.Setenv("ARGOCD_NOTIFICATION_CONTROLLER_PROCESSORS_COUNT", "4")
cmd := NewCommand()
processorsCount, err := cmd.Flags().GetInt("processors-count")
require.NoError(t, err)
assert.Equal(t, 4, processorsCount)
}
func TestNewCommandProcessorsCountInvalidEnvFallsBackToDefault(t *testing.T) {
t.Setenv("ARGOCD_NOTIFICATION_CONTROLLER_PROCESSORS_COUNT", "0")
cmd := NewCommand()
processorsCount, err := cmd.Flags().GetInt("processors-count")
require.NoError(t, err)
assert.Equal(t, 1, processorsCount)
}

View File

@@ -34,21 +34,18 @@ import (
"github.com/argoproj/argo-cd/v3/util/gpg"
"github.com/argoproj/argo-cd/v3/util/healthz"
utilio "github.com/argoproj/argo-cd/v3/util/io"
"github.com/argoproj/argo-cd/v3/util/profile"
"github.com/argoproj/argo-cd/v3/util/tls"
traceutil "github.com/argoproj/argo-cd/v3/util/trace"
)
const (
// CLIName is the name of the CLI
cliName = "argocd-repo-server"
)
var (
gnuPGSourcePath = env.StringFromEnv(common.EnvGPGDataPath, "/app/config/gpg/source")
pauseGenerationAfterFailedGenerationAttempts = env.ParseNumFromEnv(common.EnvPauseGenerationAfterFailedAttempts, 3, 0, math.MaxInt32)
pauseGenerationOnFailureForMinutes = env.ParseNumFromEnv(common.EnvPauseGenerationMinutes, 60, 0, math.MaxInt32)
pauseGenerationOnFailureForRequests = env.ParseNumFromEnv(common.EnvPauseGenerationRequests, 0, 0, math.MaxInt32)
gitSubmoduleEnabled = env.ParseBoolFromEnv(common.EnvGitSubmoduleEnabled, true)
helmUserAgent = env.StringFromEnv(common.EnvHelmUserAgent, "")
)
func NewCommand() *cobra.Command {
@@ -83,7 +80,7 @@ func NewCommand() *cobra.Command {
enableBuiltinGitConfig bool
)
command := cobra.Command{
Use: cliName,
Use: common.CommandRepoServer,
Short: "Run ArgoCD Repository Server",
Long: "ArgoCD Repository Server is an internal service which maintains a local cache of the Git repository holding the application manifests, and is responsible for generating and returning the Kubernetes manifests. This command runs Repository Server in the foreground. It can be configured by following options.",
DisableAutoGenTag: true,
@@ -157,6 +154,7 @@ func NewCommand() *cobra.Command {
CMPUseManifestGeneratePaths: cmpUseManifestGeneratePaths,
OCIMediaTypes: ociMediaTypes,
EnableBuiltinGitConfig: enableBuiltinGitConfig,
HelmUserAgent: helmUserAgent,
}, askPassServer)
errors.CheckError(err)
@@ -175,7 +173,8 @@ func NewCommand() *cobra.Command {
listener, err := lc.Listen(ctx, "tcp", fmt.Sprintf("%s:%d", listenHost, listenPort))
errors.CheckError(err)
healthz.ServeHealthCheck(http.DefaultServeMux, func(r *http.Request) error {
mux := http.NewServeMux()
healthz.ServeHealthCheck(mux, func(r *http.Request) error {
if val, ok := r.URL.Query()["full"]; ok && len(val) > 0 && val[0] == "true" {
// connect to itself to make sure repo server is able to serve connection
// used by liveness probe to auto restart repo server
@@ -197,8 +196,9 @@ func NewCommand() *cobra.Command {
}
return nil
})
http.Handle("/metrics", metricsServer.GetHandler())
go func() { errors.CheckError(http.ListenAndServe(fmt.Sprintf("%s:%d", metricsHost, metricsPort), nil)) }()
mux.Handle("/metrics", metricsServer.GetHandler())
profile.RegisterProfiler(mux)
go func() { errors.CheckError(http.ListenAndServe(fmt.Sprintf("%s:%d", metricsHost, metricsPort), mux)) }()
go func() { errors.CheckError(askPassServer.Run()) }()
if gpg.IsGPGEnabled() {
@@ -223,13 +223,11 @@ func NewCommand() *cobra.Command {
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
wg.Go(func() {
s := <-sigCh
log.Printf("got signal %v, attempting graceful shutdown", s)
grpc.GracefulStop()
wg.Done()
}()
})
log.Println("starting grpc server")
err = grpc.Serve(listener)

View File

@@ -101,7 +101,7 @@ func NewCommand() *cobra.Command {
enableK8sEvent []string
)
command := &cobra.Command{
Use: cliName,
Use: common.CommandServer,
Short: "Run the ArgoCD API server",
Long: "The API server is a gRPC/REST server which exposes the API consumed by the Web UI, CLI, and CI/CD systems. This command runs API server in the foreground. It can be configured by following options.",
DisableAutoGenTag: true,
@@ -307,7 +307,7 @@ func NewCommand() *cobra.Command {
command.Flags().BoolVar(&disableAuth, "disable-auth", env.ParseBoolFromEnv("ARGOCD_SERVER_DISABLE_AUTH", false), "Disable client authentication")
command.Flags().StringVar(&contentTypes, "api-content-types", env.StringFromEnv("ARGOCD_API_CONTENT_TYPES", "application/json", env.StringFromEnvOpts{AllowEmpty: true}), "Semicolon separated list of allowed content types for non GET api requests. Any content type is allowed if empty.")
command.Flags().BoolVar(&enableGZip, "enable-gzip", env.ParseBoolFromEnv("ARGOCD_SERVER_ENABLE_GZIP", true), "Enable GZIP compression")
command.AddCommand(cli.NewVersionCmd(cliName))
command.AddCommand(cli.NewVersionCmd(common.CommandServer))
command.Flags().StringVar(&listenHost, "address", env.StringFromEnv("ARGOCD_SERVER_LISTEN_ADDRESS", common.DefaultAddressAPIServer), "Listen on given address")
command.Flags().IntVar(&listenPort, "port", common.DefaultPortAPIServer, "Listen on given port")
command.Flags().StringVar(&metricsHost, env.StringFromEnv("ARGOCD_SERVER_METRICS_LISTEN_ADDRESS", "metrics-address"), common.DefaultAddressAPIServerMetrics, "Listen for metrics on given address")

View File

@@ -1,6 +0,0 @@
package commands
const (
// cliName is the name of the CLI
cliName = "argocd-server"
)

View File

@@ -11,11 +11,13 @@ import (
"time"
timeutil "github.com/argoproj/pkg/v2/time"
"github.com/golang-jwt/jwt/v5"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"golang.org/x/term"
"sigs.k8s.io/yaml"
jwtutil "github.com/argoproj/argo-cd/v3/util/jwt"
"github.com/argoproj/argo-cd/v3/util/rbac"
"github.com/argoproj/argo-cd/v3/cmd/argocd/commands/headless"
@@ -60,6 +62,7 @@ func NewAccountCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
command.AddCommand(NewAccountGenerateTokenCommand(clientOpts))
command.AddCommand(NewAccountGetCommand(clientOpts))
command.AddCommand(NewAccountDeleteTokenCommand(clientOpts))
command.AddCommand(NewAccountSessionTokenCommand(clientOpts))
command.AddCommand(NewBcryptCmd())
return command
}
@@ -134,7 +137,7 @@ has appropriate RBAC permissions to change other accounts.
errors.CheckError(err)
claims, err := configCtx.User.Claims()
errors.CheckError(err)
tokenString := passwordLogin(ctx, acdClient, localconfig.GetUsername(claims.Subject), newPassword)
tokenString := passwordLogin(ctx, acdClient, localconfig.GetUsername(jwtutil.StringField(claims, "sub")), newPassword)
localCfg.UpsertUser(localconfig.User{
Name: localCfg.CurrentContext,
AuthToken: tokenString,
@@ -448,3 +451,90 @@ argocd account delete-token --account <account-name> ID`,
cmd.Flags().StringVarP(&account, "account", "a", "", "Account name. Defaults to the current account.")
return cmd
}
func NewAccountSessionTokenCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var output string
cmd := &cobra.Command{
Use: "session-token",
Short: "Display current session token",
Long: `Display the current session token for authentication.
Automatically refreshes expired tokens using refresh token (SSO users).
For local users: Shows current token (manual relogin needed if expired)`,
Example: `# Display current session token (automatically refreshes if needed)
argocd account session-token
# Show detailed token information
argocd account session-token -o json
# Use in scripts
export ARGOCD_AUTH_TOKEN=$(argocd account session-token)
curl -H "Authorization: Bearer $ARGOCD_AUTH_TOKEN" $ARGOCD_SERVER/api/v1/applications`,
Run: func(_ *cobra.Command, _ []string) {
// Create client first - this handles token refresh automatically
_, err := argocdclient.NewClient(clientOpts)
if err != nil {
if strings.Contains(err.Error(), "invalid_grant") && strings.Contains(err.Error(), "Invalid refresh_token") {
log.Fatal("Refresh token is invalid or expired. Please run 'argocd relogin' to re-authenticate")
}
log.Fatal(err)
}
// Read config after client creation to get potentially refreshed token
localCfg, err := localconfig.ReadLocalConfig(clientOpts.ConfigPath)
errors.CheckError(err)
if localCfg == nil {
log.Fatal("No configuration found. Please login first with 'argocd login'")
}
configCtx, err := localCfg.ResolveContext(clientOpts.Context)
errors.CheckError(err)
if configCtx == nil {
log.Fatal("No context found. Please login first with 'argocd login'")
}
if configCtx.User.AuthToken == "" {
log.Fatal("No authentication token found. Please login first with 'argocd login'")
}
// Get token claims and validate
claims, err := configCtx.User.Claims()
if err != nil {
log.Fatal("Invalid token format. Please run 'argocd relogin'")
}
validator := jwt.NewValidator()
if validator.Validate(claims) != nil {
log.Fatal("Token is invalid or expired. Please run 'argocd relogin'")
}
switch output {
case "json":
iss := jwtutil.StringField(claims, "iss")
tokenInfo := map[string]any{
"type": "local",
"issuer": iss,
"username": localconfig.GetUsername(jwtutil.GetUserIdentifier(claims)),
"token": configCtx.User.AuthToken,
"has_refresh_token": configCtx.User.RefreshToken != "",
}
if iss != sessionutil.SessionManagerClaimsIssuer {
tokenInfo["type"] = "sso"
}
if iat, err := jwtutil.IssuedAtTime(claims); err == nil {
tokenInfo["issued_at"] = iat.Format(time.RFC3339)
}
if exp, err := jwtutil.ExpirationTime(claims); err == nil {
tokenInfo["expires_at"] = exp.Format(time.RFC3339)
}
jsonBytes, err := json.MarshalIndent(tokenInfo, "", " ")
errors.CheckError(err)
fmt.Println(string(jsonBytes))
default:
fmt.Println(configCtx.User.AuthToken)
}
},
}
cmd.Flags().StringVarP(&output, "output", "o", "", "Output format (json)")
return cmd
}

View File

@@ -183,9 +183,9 @@ func getAdditionalNamespaces(ctx context.Context, configMapsClient dynamic.Resou
namespacesListFromString := func(namespaces string) []string {
listOfNamespaces := []string{}
ss := strings.Split(namespaces, ",")
ss := strings.SplitSeq(namespaces, ",")
for _, namespace := range ss {
for namespace := range ss {
if namespace != "" {
listOfNamespaces = append(listOfNamespaces, strings.TrimSpace(namespace))
}

View File

@@ -10,8 +10,8 @@ import (
"sort"
"time"
"github.com/argoproj/gitops-engine/pkg/health"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/argoproj/argo-cd/gitops-engine/pkg/health"
"github.com/argoproj/argo-cd/gitops-engine/pkg/utils/kube"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

View File

@@ -3,9 +3,9 @@ package admin
import (
"testing"
clustermocks "github.com/argoproj/gitops-engine/pkg/cache/mocks"
"github.com/argoproj/gitops-engine/pkg/health"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
clustermocks "github.com/argoproj/argo-cd/gitops-engine/pkg/cache/mocks"
"github.com/argoproj/argo-cd/gitops-engine/pkg/health"
"github.com/argoproj/argo-cd/gitops-engine/pkg/utils/kube"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"

View File

@@ -8,7 +8,7 @@ import (
"strings"
"time"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/argoproj/argo-cd/gitops-engine/pkg/utils/kube"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
apierrors "k8s.io/apimachinery/pkg/api/errors"

View File

@@ -7,7 +7,7 @@ import (
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v3/util/security"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/argoproj/argo-cd/gitops-engine/pkg/utils/kube"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

View File

@@ -10,7 +10,7 @@ import (
"text/tabwriter"
"time"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/argoproj/argo-cd/gitops-engine/pkg/utils/kube"
"github.com/redis/go-redis/v9"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -20,7 +20,6 @@ import (
"k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/utils/ptr"
cmdutil "github.com/argoproj/argo-cd/v3/cmd/util"
"github.com/argoproj/argo-cd/v3/common"
@@ -128,19 +127,16 @@ func loadClusters(ctx context.Context, kubeClient kubernetes.Interface, appClien
batchSize := 10
batchesCount := int(math.Ceil(float64(len(clusters)) / float64(batchSize)))
for batchNum := 0; batchNum < batchesCount; batchNum++ {
for batchNum := range batchesCount {
batchStart := batchSize * batchNum
batchEnd := batchSize * (batchNum + 1)
if batchEnd > len(clustersList.Items) {
batchEnd = len(clustersList.Items)
}
batchEnd := min((batchSize * (batchNum + 1)), len(clustersList.Items))
batch := clustersList.Items[batchStart:batchEnd]
_ = kube.RunAllAsync(len(batch), func(i int) error {
clusterShard := 0
cluster := batch[i]
if replicas > 0 {
clusterShard = clusterShards[cluster.Server]
cluster.Shard = ptr.To(int64(clusterShard))
cluster.Shard = new(int64(clusterShard))
log.Infof("Cluster with uid: %s will be processed by shard %d", cluster.ID, clusterShard)
}
if shard != -1 && clusterShard != shard {

View File

@@ -14,7 +14,6 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
"k8s.io/utils/ptr"
)
func Test_loadClusters(t *testing.T) {
@@ -72,9 +71,9 @@ func Test_loadClusters(t *testing.T) {
ConnectionState: v1alpha1.ConnectionState{
Status: "Successful",
},
ServerVersion: ".",
ServerVersion: "0.0.0",
},
Shard: ptr.To(int64(0)),
Shard: new(int64(0)),
},
Namespaces: []string{"test"},
}}

View File

@@ -7,7 +7,7 @@ import (
"io"
"os"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/argoproj/argo-cd/gitops-engine/pkg/utils/kube"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/yaml"

View File

@@ -4,6 +4,7 @@ import (
"log"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
@@ -60,7 +61,11 @@ func NewNotificationsCommand() *cobra.Command {
tlsConfig.Certificates = pool
}
repoClientset := apiclient.NewRepoServerClientset(argocdRepoServer, 5, tlsConfig)
argocdService, err = service.NewArgoCDService(kubernetes.NewForConfigOrDie(k8sCfg), ns, repoClientset)
dynamicClient, err := dynamic.NewForConfig(k8sCfg)
if err != nil {
log.Fatalf("Failed to create dynamic client: %v", err)
}
argocdService, err = service.NewArgoCDService(kubernetes.NewForConfigOrDie(k8sCfg), dynamicClient, ns, repoClientset)
if err != nil {
log.Fatalf("Failed to initialize Argo CD service: %v", err)
}

View File

@@ -17,7 +17,7 @@ import (
utilio "github.com/argoproj/argo-cd/v3/util/io"
"github.com/argoproj/argo-cd/v3/util/templates"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/argoproj/argo-cd/gitops-engine/pkg/utils/kube"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/clientcmd"

View File

@@ -23,7 +23,7 @@ func generateRandomPassword() (string, error) {
const initialPasswordLength = 16
const letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"
randBytes := make([]byte, initialPasswordLength)
for i := 0; i < initialPasswordLength; i++ {
for i := range initialPasswordLength {
num, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters))))
if err != nil {
return "", err

View File

@@ -7,12 +7,13 @@ import (
"fmt"
"os"
"reflect"
"slices"
"sort"
"strconv"
"strings"
"text/tabwriter"
healthutil "github.com/argoproj/gitops-engine/pkg/health"
healthutil "github.com/argoproj/argo-cd/gitops-engine/pkg/health"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
@@ -271,9 +272,7 @@ func NewValidateSettingsCommand(cmdCtx commandContext) *cobra.Command {
for k := range validatorsByGroup {
allGroups = append(allGroups, k)
}
sort.Slice(allGroups, func(i, j int) bool {
return allGroups[i] < allGroups[j]
})
slices.Sort(allGroups)
command := &cobra.Command{
Use: "validate",

View File

@@ -322,6 +322,7 @@ func getPolicy(ctx context.Context, policyFile string, kubeClient kubernetes.Int
}
// getPolicyFromFile loads a RBAC policy from given path
// nolint:unparam // complains about the error being always nil which is false-positive
func getPolicyFromFile(policyFile string) (string, string, string, error) {
var (
userPolicy string

View File

@@ -19,11 +19,11 @@ import (
"golang.org/x/sync/errgroup"
"github.com/argoproj/gitops-engine/pkg/health"
"github.com/argoproj/gitops-engine/pkg/sync/common"
"github.com/argoproj/gitops-engine/pkg/sync/hook"
"github.com/argoproj/gitops-engine/pkg/sync/ignore"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/argoproj/argo-cd/gitops-engine/pkg/health"
"github.com/argoproj/argo-cd/gitops-engine/pkg/sync/common"
"github.com/argoproj/argo-cd/gitops-engine/pkg/sync/hook"
"github.com/argoproj/argo-cd/gitops-engine/pkg/sync/ignore"
"github.com/argoproj/argo-cd/gitops-engine/pkg/utils/kube"
grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/retry"
"github.com/mattn/go-isatty"
log "github.com/sirupsen/logrus"
@@ -35,7 +35,6 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
k8swatch "k8s.io/apimachinery/pkg/watch"
"k8s.io/utils/ptr"
"sigs.k8s.io/yaml"
"github.com/argoproj/argo-cd/v3/cmd/argocd/commands/headless"
@@ -46,7 +45,7 @@ import (
argocdclient "github.com/argoproj/argo-cd/v3/pkg/apiclient"
"github.com/argoproj/argo-cd/v3/pkg/apiclient/application"
resourceutil "github.com/argoproj/gitops-engine/pkg/sync/resource"
resourceutil "github.com/argoproj/argo-cd/gitops-engine/pkg/sync/resource"
clusterpkg "github.com/argoproj/argo-cd/v3/pkg/apiclient/cluster"
projectpkg "github.com/argoproj/argo-cd/v3/pkg/apiclient/project"
@@ -602,17 +601,17 @@ func NewApplicationLogsCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
stream, err := appIf.PodLogs(ctx, &application.ApplicationPodLogsQuery{
Name: &appName,
Group: &group,
Namespace: ptr.To(namespace),
Namespace: new(namespace),
Kind: &kind,
ResourceName: &resourceName,
Follow: ptr.To(follow),
TailLines: ptr.To(tail),
SinceSeconds: ptr.To(sinceSeconds),
Follow: new(follow),
TailLines: new(tail),
SinceSeconds: new(sinceSeconds),
UntilTime: &untilTime,
Filter: &filter,
MatchCase: ptr.To(matchCase),
Container: ptr.To(container),
Previous: ptr.To(previous),
MatchCase: new(matchCase),
Container: new(container),
Previous: new(previous),
AppNamespace: &appNs,
})
if err != nil {
@@ -718,7 +717,7 @@ func printAppSummaryTable(app *argoappv1.Application, appURL string, windows *ar
var syncPolicy string
if app.Spec.SyncPolicy != nil && app.Spec.SyncPolicy.IsAutomatedSyncEnabled() {
syncPolicy = "Automated"
if app.Spec.SyncPolicy.Automated.Prune {
if app.Spec.SyncPolicy.Automated.GetPrune() {
syncPolicy += " (Prune)"
}
} else {
@@ -996,6 +995,9 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C
c.HelpFunc()(c, args)
os.Exit(1)
}
if sourceName != "" && sourcePosition != -1 {
errors.Fatal(errors.ErrorGeneric, "Only one of source-position and source-name can be specified.")
}
appName, appNs := argo.ParseFromQualifiedName(args[0], appNamespace)
conn, appIf := headless.NewClientOrDie(clientOpts, c).NewApplicationClientOrDie()
@@ -1003,11 +1005,6 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C
app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: &appName, AppNamespace: &appNs})
errors.CheckError(err)
sourceName = appOpts.SourceName
if sourceName != "" && sourcePosition != -1 {
errors.Fatal(errors.ErrorGeneric, "Only one of source-position and source-name can be specified.")
}
if sourceName != "" {
sourceNameToPosition := getSourceNameToPositionMap(app)
pos, ok := sourceNameToPosition[sourceName]
@@ -1070,6 +1067,7 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C
command.Flags().BoolVar(&opts.passCredentials, "pass-credentials", false, "Unset passCredentials")
command.Flags().BoolVar(&opts.ref, "ref", false, "Unset ref on the source")
command.Flags().IntVar(&sourcePosition, "source-position", -1, "Position of the source from the list of sources of the app. Counting starts at 1.")
command.Flags().StringVar(&sourceName, "source-name", "", "Name of the source from the list of sources of the app.")
return command
}
@@ -1872,7 +1870,7 @@ func NewApplicationListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
conn, appIf := headless.NewClientOrDie(clientOpts, c).NewApplicationClientOrDie()
defer utilio.Close(conn)
apps, err := appIf.List(ctx, &application.ApplicationQuery{
Selector: ptr.To(selector),
Selector: new(selector),
AppNamespace: &appNamespace,
})
@@ -1920,7 +1918,7 @@ func formatSyncPolicy(app argoappv1.Application) string {
return "Manual"
}
policy := "Auto"
if app.Spec.SyncPolicy.Automated.Prune {
if app.Spec.SyncPolicy.Automated.GetPrune() {
policy = policy + "-Prune"
}
return policy
@@ -1988,8 +1986,8 @@ func parseSelectedResources(resources []string) ([]*argoappv1.SyncOperationResou
for _, resource := range resources {
isExcluded := false
// check if the resource flag starts with a '!'
if strings.HasPrefix(resource, resourceExcludeIndicator) {
resource = strings.TrimPrefix(resource, resourceExcludeIndicator)
if after, ok := strings.CutPrefix(resource, resourceExcludeIndicator); ok {
resource = after
isExcluded = true
}
fields := strings.Split(resource, resourceFieldDelimiter)
@@ -2073,7 +2071,7 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
closer, appIf := acdClient.NewApplicationClientOrDie()
defer utilio.Close(closer)
if selector != "" {
list, err := appIf.List(ctx, &application.ApplicationQuery{Selector: ptr.To(selector)})
list, err := appIf.List(ctx, &application.ApplicationQuery{Selector: new(selector)})
errors.CheckError(err)
for _, i := range list.Items {
appNames = append(appNames, i.QualifiedName())
@@ -2257,7 +2255,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
appNames := args
if selector != "" || len(projects) > 0 {
list, err := appIf.List(ctx, &application.ApplicationQuery{
Selector: ptr.To(selector),
Selector: new(selector),
AppNamespace: &appNamespace,
Projects: projects,
})
@@ -2431,7 +2429,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
Backoff: &argoappv1.Backoff{
Duration: retryBackoffDuration.String(),
MaxDuration: retryBackoffMaxDuration.String(),
Factor: ptr.To(retryBackoffFactor),
Factor: new(retryBackoffFactor),
},
}
}
@@ -2525,7 +2523,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
func getAppNamesBySelector(ctx context.Context, appIf application.ApplicationServiceClient, selector string) ([]string, error) {
appNames := []string{}
if selector != "" {
list, err := appIf.List(ctx, &application.ApplicationQuery{Selector: ptr.To(selector)})
list, err := appIf.List(ctx, &application.ApplicationQuery{Selector: new(selector)})
if err != nil {
return []string{}, err
}
@@ -2703,7 +2701,7 @@ func checkResourceStatus(watch watchOpts, healthStatus string, syncStatus string
func resourceParentChild(ctx context.Context, acdClient argocdclient.Client, appName string, appNs string) (map[string]argoappv1.ResourceNode, map[string][]string, map[string]struct{}, map[string]*resourceState) {
_, appIf := acdClient.NewApplicationClientOrDie()
mapUIDToNode, mapParentToChild, parentNode := parentChildDetails(ctx, appIf, appName, appNs)
app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: ptr.To(appName), AppNamespace: ptr.To(appNs)})
app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: new(appName), AppNamespace: new(appNs)})
errors.CheckError(err)
mapNodeNameToResourceState := make(map[string]*resourceState)
for _, res := range getResourceStates(app, nil) {
@@ -3135,8 +3133,8 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr
_, err = appIf.Rollback(ctx, &application.ApplicationRollbackRequest{
Name: &appName,
AppNamespace: &appNs,
Id: ptr.To(depInfo.ID),
Prune: ptr.To(prune),
Id: new(depInfo.ID),
Prune: new(prune),
})
errors.CheckError(err)
@@ -3288,7 +3286,7 @@ func NewApplicationManifestsCommand(clientOpts *argocdclient.ClientOptions) *cob
q := application.ApplicationManifestQuery{
Name: &appName,
AppNamespace: &appNs,
Revision: ptr.To(revision),
Revision: new(revision),
Revisions: revisions,
SourcePositions: sourcePositions,
}
@@ -3304,7 +3302,7 @@ func NewApplicationManifestsCommand(clientOpts *argocdclient.ClientOptions) *cob
q := application.ApplicationManifestQuery{
Name: &appName,
AppNamespace: &appNs,
Revision: ptr.To(revision),
Revision: new(revision),
}
res, err := appIf.GetManifests(ctx, &q)
errors.CheckError(err)
@@ -3326,7 +3324,6 @@ func NewApplicationManifestsCommand(clientOpts *argocdclient.ClientOptions) *cob
default:
log.Fatalf("Unknown source type '%s'", source)
}
for _, obj := range unstructureds {
fmt.Println("---")
yamlBytes, err := yaml.Marshal(obj)
@@ -3666,7 +3663,7 @@ func NewApplicationConfirmDeletionCommand(clientOpts *argocdclient.ClientOptions
_, err = appIf.Update(ctx, &application.ApplicationUpdateRequest{
Application: app,
Validate: ptr.To(false),
Validate: new(false),
Project: &app.Spec.Project,
})
errors.CheckError(err)

View File

@@ -11,7 +11,6 @@ import (
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"google.golang.org/grpc/codes"
"k8s.io/utils/ptr"
"sigs.k8s.io/yaml"
"github.com/argoproj/argo-cd/v3/cmd/argocd/commands/headless"
@@ -95,11 +94,11 @@ func NewApplicationResourceActionsListCommand(clientOpts *argocdclient.ClientOpt
availActionsForResource, err := appIf.ListResourceActions(ctx, &applicationpkg.ApplicationResourceRequest{
Name: &appName,
AppNamespace: &appNs,
Namespace: ptr.To(obj.GetNamespace()),
ResourceName: ptr.To(obj.GetName()),
Group: ptr.To(gvk.Group),
Kind: ptr.To(gvk.Kind),
Version: ptr.To(gvk.Version),
Namespace: new(obj.GetNamespace()),
ResourceName: new(obj.GetName()),
Group: new(gvk.Group),
Kind: new(gvk.Kind),
Version: new(gvk.Version),
})
errors.CheckError(err)
for _, action := range availActionsForResource.Actions {
@@ -195,12 +194,12 @@ func NewApplicationResourceActionsRunCommand(clientOpts *argocdclient.ClientOpti
_, err := appIf.RunResourceActionV2(ctx, &applicationpkg.ResourceActionRunRequestV2{
Name: &appName,
AppNamespace: &appNs,
Namespace: ptr.To(obj.GetNamespace()),
ResourceName: ptr.To(objResourceName),
Group: ptr.To(gvk.Group),
Kind: ptr.To(gvk.Kind),
Version: ptr.To(gvk.GroupVersion().Version),
Action: ptr.To(actionName),
Namespace: new(obj.GetNamespace()),
ResourceName: new(objResourceName),
Group: new(gvk.Group),
Kind: new(gvk.Kind),
Version: new(gvk.GroupVersion().Version),
Action: new(actionName),
// TODO: add support for parameters
})
if err == nil {
@@ -214,12 +213,12 @@ func NewApplicationResourceActionsRunCommand(clientOpts *argocdclient.ClientOpti
_, err = appIf.RunResourceAction(ctx, &applicationpkg.ResourceActionRunRequest{
Name: &appName,
AppNamespace: &appNs,
Namespace: ptr.To(obj.GetNamespace()),
ResourceName: ptr.To(objResourceName),
Group: ptr.To(gvk.Group),
Kind: ptr.To(gvk.Kind),
Version: ptr.To(gvk.GroupVersion().Version),
Action: ptr.To(actionName),
Namespace: new(obj.GetNamespace()),
ResourceName: new(objResourceName),
Group: new(gvk.Group),
Kind: new(gvk.Kind),
Version: new(gvk.GroupVersion().Version),
Action: new(actionName),
})
errors.CheckError(err)
}

View File

@@ -43,9 +43,49 @@ func TestPrintTreeViewAppResources(t *testing.T) {
printTreeViewAppResourcesNotOrphaned(nodeMapping, mapParentToChild, parentNode, w)
require.NoError(t, w.Flush())
output := buf.String()
t.Logf("Output:\n%s", output)
assert.Contains(t, output, "Rollout")
assert.Contains(t, output, "argoproj.io")
assert.Contains(t, output, "└─apps ReplicaSet sandbox-rollout-numalogic-demo numalogic-rollout-demo-5dcd5457d5 No")
assert.Contains(t, output, " └─ Pod sandbox-rollout-numalogic-demo numalogic-rollout-demo-5dcd5457d5-6trpt No")
}
func TestPrintTreeViewAppResourcesWithMultipleChildren(t *testing.T) {
var nodes [4]v1alpha1.ResourceNode
// Parent
nodes[0].ResourceRef = v1alpha1.ResourceRef{Group: "argoproj.io", Kind: "Rollout", Namespace: "ns", Name: "rollout", UID: "root"}
// Child 1
nodes[1].ResourceRef = v1alpha1.ResourceRef{Group: "apps", Kind: "ReplicaSet", Namespace: "ns", Name: "rs1", UID: "rs1"}
nodes[1].ParentRefs = []v1alpha1.ResourceRef{{UID: "root"}}
// Child 2
nodes[2].ResourceRef = v1alpha1.ResourceRef{Group: "apps", Kind: "ReplicaSet", Namespace: "ns", Name: "rs2", UID: "rs2"}
nodes[2].ParentRefs = []v1alpha1.ResourceRef{{UID: "root"}}
// Grandchild
nodes[3].ResourceRef = v1alpha1.ResourceRef{Group: "", Kind: "Pod", Namespace: "ns", Name: "pod1", UID: "pod1"}
nodes[3].ParentRefs = []v1alpha1.ResourceRef{{UID: "rs1"}}
nodeMapping := make(map[string]v1alpha1.ResourceNode)
mapParentToChild := make(map[string][]string)
parentNode := make(map[string]struct{})
for _, node := range nodes {
nodeMapping[node.UID] = node
if len(node.ParentRefs) > 0 {
mapParentToChild[node.ParentRefs[0].UID] = append(mapParentToChild[node.ParentRefs[0].UID], node.UID)
} else {
parentNode[node.UID] = struct{}{}
}
}
buf := &bytes.Buffer{}
w := tabwriter.NewWriter(buf, 0, 0, 2, ' ', 0)
printTreeViewAppResourcesNotOrphaned(nodeMapping, mapParentToChild, parentNode, w)
require.NoError(t, w.Flush())
output := buf.String()
t.Logf("Output:\n%s", output)
assert.Contains(t, output, "├─apps ReplicaSet ns rs1")
assert.Contains(t, output, "│ └─ Pod ns pod1")
assert.Contains(t, output, "└─apps ReplicaSet ns rs2")
}
func TestPrintTreeViewDetailedAppResources(t *testing.T) {
@@ -82,10 +122,11 @@ func TestPrintTreeViewDetailedAppResources(t *testing.T) {
printDetailedTreeViewAppResourcesNotOrphaned(nodeMapping, mapParentToChild, parentNode, w)
require.NoError(t, w.Flush())
output := buf.String()
t.Logf("Output:\n%s", output)
assert.Contains(t, output, "Rollout")
assert.Contains(t, output, "Degraded")
assert.Contains(t, output, "Readiness Gate failed")
assert.Contains(t, output, "argoproj.io Rollout sandbox-rollout-numalogic-demo numalogic-rollout-demo No <unknown> Degraded Readiness Gate failed")
assert.Contains(t, output, "└─apps ReplicaSet sandbox-rollout-numalogic-demo numalogic-rollout-demo-5dcd5457d5 No")
assert.Contains(t, output, " └─ Pod sandbox-rollout-numalogic-demo numalogic-rollout-demo-5dcd5457d5-6trpt No")
}
func TestPrintResourcesTree(t *testing.T) {

View File

@@ -10,6 +10,8 @@ import (
"gopkg.in/yaml.v3"
"github.com/argoproj/argo-cd/v3/util/templates"
"github.com/argoproj/argo-cd/v3/cmd/argocd/commands/utils"
"github.com/argoproj/argo-cd/v3/cmd/util"
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
@@ -18,7 +20,6 @@ import (
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/ptr"
"github.com/argoproj/argo-cd/v3/cmd/argocd/commands/headless"
argocdclient "github.com/argoproj/argo-cd/v3/pkg/apiclient"
@@ -87,7 +88,7 @@ func NewApplicationGetResourceCommand(clientOpts *argocdclient.ClientOptions) *c
// Get manifests of resources
// If resource name is "" find all resources of that kind
var resources []unstructured.Unstructured
var fetchedStr string
var resourceNames []string
for _, r := range tree.Nodes {
if (resourceName != "" && r.Name != resourceName) || (group != "" && r.Group != group) || r.Kind != kind {
continue
@@ -117,14 +118,11 @@ func NewApplicationGetResourceCommand(clientOpts *argocdclient.ClientOptions) *c
obj = filterFieldsFromObject(obj, filteredFields)
}
fetchedStr += obj.GetName() + ", "
resourceNames = append(resourceNames, obj.GetName())
resources = append(resources, *obj)
}
fetchedStr := strings.Join(resourceNames, ", ")
printManifests(&resources, len(filteredFields) > 0, resourceName == "", output)
if fetchedStr != "" {
fetchedStr = strings.TrimSuffix(fetchedStr, ", ")
}
log.Infof("Resources '%s' fetched", fetchedStr)
}
@@ -338,14 +336,14 @@ func NewApplicationPatchResourceCommand(clientOpts *argocdclient.ClientOptions)
_, err = appIf.PatchResource(ctx, &applicationpkg.ApplicationResourcePatchRequest{
Name: &appName,
AppNamespace: &appNs,
Namespace: ptr.To(obj.GetNamespace()),
ResourceName: ptr.To(obj.GetName()),
Version: ptr.To(gvk.Version),
Group: ptr.To(gvk.Group),
Kind: ptr.To(gvk.Kind),
Patch: ptr.To(patch),
PatchType: ptr.To(patchType),
Project: ptr.To(project),
Namespace: new(obj.GetNamespace()),
ResourceName: new(obj.GetName()),
Version: new(gvk.Version),
Group: new(gvk.Group),
Kind: new(gvk.Kind),
Patch: new(patch),
PatchType: new(patchType),
Project: new(project),
})
errors.CheckError(err)
log.Infof("Resource '%s' patched", obj.GetName())
@@ -411,14 +409,14 @@ func NewApplicationDeleteResourceCommand(clientOpts *argocdclient.ClientOptions)
_, err = appIf.DeleteResource(ctx, &applicationpkg.ApplicationResourceDeleteRequest{
Name: &appName,
AppNamespace: &appNs,
Namespace: ptr.To(obj.GetNamespace()),
ResourceName: ptr.To(obj.GetName()),
Version: ptr.To(gvk.Version),
Group: ptr.To(gvk.Group),
Kind: ptr.To(gvk.Kind),
Namespace: new(obj.GetNamespace()),
ResourceName: new(obj.GetName()),
Version: new(gvk.Version),
Group: new(gvk.Group),
Kind: new(gvk.Kind),
Force: &force,
Orphan: &orphan,
Project: ptr.To(project),
Project: new(project),
})
errors.CheckError(err)
log.Infof("Resource '%s' deleted", obj.GetName())
@@ -533,7 +531,20 @@ func NewApplicationListResourcesCommand(clientOpts *argocdclient.ClientOptions)
)
command := &cobra.Command{
Use: "resources APPNAME",
Short: "List resource of application",
Short: "List resources of application",
Example: templates.Examples(`
# List first-level resources of application
argocd app resources my-app --refresh
# List only the orphaned resources of application
argocd app resources my-app --orphaned
# Shows resource hierarchy with parent-child relationships
argocd app resources my-app --output tree
# Shows resource hierarchy with parent-child relationships including information about age, health and reason
argocd app resources my-app --output tree=detailed
`),
Run: func(c *cobra.Command, args []string) {
ctx := c.Context()
if len(args) != 1 {
@@ -554,7 +565,9 @@ func NewApplicationListResourcesCommand(clientOpts *argocdclient.ClientOptions)
},
}
command.Flags().BoolVar(&orphaned, "orphaned", false, "Lists only orphaned resources")
command.Flags().StringVar(&output, "output", "", "Provides the tree view of the resources")
command.Flags().StringVar(&output, "output", "", `Output format. One of: tree|tree=detailed.
tree: Shows resource hierarchy with parent-child relationships
tree=detailed: Same as tree, but includes AGE, HEALTH, and REASON columns`)
command.Flags().StringVar(&project, "project", "", `The name of the application's project - specifying this allows the command to report "not found" instead of "permission denied" if the app does not exist`)
return command
}

View File

@@ -1,19 +1,22 @@
package commands
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"os"
"os/exec"
"slices"
"strings"
"testing"
"time"
"github.com/argoproj/gitops-engine/pkg/health"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/argoproj/argo-cd/gitops-engine/pkg/health"
"github.com/argoproj/argo-cd/gitops-engine/pkg/utils/kube"
"github.com/coreos/go-oidc/v3/oidc"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
@@ -440,7 +443,7 @@ func TestFormatSyncPolicy(t *testing.T) {
Spec: v1alpha1.ApplicationSpec{
SyncPolicy: &v1alpha1.SyncPolicy{
Automated: &v1alpha1.SyncPolicyAutomated{
Prune: true,
Prune: new(true),
},
},
},
@@ -458,7 +461,7 @@ func TestFormatConditionSummary(t *testing.T) {
Spec: v1alpha1.ApplicationSpec{
SyncPolicy: &v1alpha1.SyncPolicy{
Automated: &v1alpha1.SyncPolicyAutomated{
Prune: true,
Prune: new(true),
},
},
},
@@ -673,7 +676,7 @@ func TestPrintAppSummaryTable(t *testing.T) {
Spec: v1alpha1.ApplicationSpec{
SyncPolicy: &v1alpha1.SyncPolicy{
Automated: &v1alpha1.SyncPolicyAutomated{
Prune: true,
Prune: new(true),
},
},
Project: "default",
@@ -761,7 +764,7 @@ func TestPrintAppSummaryTable_MultipleSources(t *testing.T) {
Spec: v1alpha1.ApplicationSpec{
SyncPolicy: &v1alpha1.SyncPolicy{
Automated: &v1alpha1.SyncPolicyAutomated{
Prune: true,
Prune: new(true),
},
},
Project: "default",
@@ -1047,6 +1050,39 @@ func TestPrintApplicationNames(t *testing.T) {
require.Equalf(t, output, expectation, "Incorrect print params output %q, should be %q", output, expectation)
}
func TestNewApplicationUnsetCommand_Validation(t *testing.T) {
if os.Getenv("BE_CRASHER") == "1" {
cmd := NewApplicationUnsetCommand(nil)
cmd.SetArgs([]string{"my-app", "--source-position", "1", "--source-name", "test"})
_ = cmd.Execute()
}
cmd := exec.CommandContext(context.Background(), os.Args[0], "-test.run=TestNewApplicationUnsetCommand_Validation")
cmd.Env = append(os.Environ(), "BE_CRASHER=1")
var stderr bytes.Buffer
cmd.Stderr = &stderr
err := cmd.Run()
if e, ok := errors.AsType[*exec.ExitError](err); ok && !e.Success() {
assert.Contains(t, stderr.String(), "Only one of source-position and source-name can be specified.")
return
}
t.Fatalf("process ran with err %v, want exit status 1", err)
}
func TestNewApplicationUnsetCommand_Flags(t *testing.T) {
cmd := NewApplicationUnsetCommand(nil)
assert.NotNil(t, cmd)
flag := cmd.Flags().Lookup("source-name")
assert.NotNil(t, flag)
assert.Equal(t, "source-name", flag.Name)
flag = cmd.Flags().Lookup("source-position")
assert.NotNil(t, flag)
assert.Equal(t, "source-position", flag.Name)
}
func Test_unset(t *testing.T) {
kustomizeSource := &v1alpha1.ApplicationSource{
Kustomize: &v1alpha1.ApplicationSourceKustomize{
@@ -2079,7 +2115,7 @@ func (c *fakeAppServiceClient) Get(_ context.Context, _ *applicationpkg.Applicat
Spec: v1alpha1.ApplicationSpec{
SyncPolicy: &v1alpha1.SyncPolicy{
Automated: &v1alpha1.SyncPolicyAutomated{
Prune: true,
Prune: new(true),
},
},
Project: "default",
@@ -2386,3 +2422,22 @@ func (c *fakeAcdClient) WatchApplicationWithRetry(_ context.Context, _ string, _
}()
return appEventsCh
}
func (c *fakeAcdClient) WatchApplicationSetWithRetry(_ context.Context, _ string, _ string) chan *v1alpha1.ApplicationSetWatchEvent {
appSetEventsCh := make(chan *v1alpha1.ApplicationSetWatchEvent)
go func() {
defer close(appSetEventsCh)
addedEvent := &v1alpha1.ApplicationSetWatchEvent{
Type: watch.Added,
ApplicationSet: v1alpha1.ApplicationSet{
Status: v1alpha1.ApplicationSetStatus{
Conditions: []v1alpha1.ApplicationSetCondition{
{Type: v1alpha1.ApplicationSetConditionResourcesUpToDate, Status: v1alpha1.ApplicationSetConditionStatusTrue},
},
},
},
}
appSetEventsCh <- addedEvent
}()
return appSetEventsCh
}

View File

@@ -1,12 +1,15 @@
package commands
import (
"context"
"fmt"
"io"
"os"
"reflect"
"text/tabwriter"
k8swatch "k8s.io/apimachinery/pkg/watch"
"github.com/mattn/go-isatty"
"github.com/spf13/cobra"
"google.golang.org/grpc/codes"
@@ -115,8 +118,10 @@ func NewApplicationSetGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.
// NewApplicationSetCreateCommand returns a new instance of an `argocd appset create` command
func NewApplicationSetCreateCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var output string
var upsert, dryRun bool
var (
output string
upsert, dryRun, wait bool
)
command := &cobra.Command{
Use: "create",
Short: "Create one or more ApplicationSets",
@@ -200,11 +205,18 @@ func NewApplicationSetCreateCommand(clientOpts *argocdclient.ClientOptions) *cob
default:
errors.CheckError(fmt.Errorf("unknown output format: %s", output))
}
if wait && !dryRun {
err := waitForApplicationSetResourcesUpToDate(ctx, argocdClient, created.QualifiedName())
errors.CheckError(err)
c.PrintErrf("ApplicationSet '%s' resources are up to date\n", created.Name)
}
}
},
}
command.Flags().BoolVar(&upsert, "upsert", false, "Allows to override ApplicationSet with the same name even if supplied ApplicationSet spec is different from existing spec")
command.Flags().BoolVar(&dryRun, "dry-run", false, "Allows to evaluate the ApplicationSet template on the server to get a preview of the applications that would be created")
command.Flags().BoolVar(&wait, "wait", false, "Wait until the ApplicationSet's resources are up to date. Will block indefinitely if the ApplicationSet has errors")
command.Flags().StringVarP(&output, "output", "o", "wide", "Output format. One of: json|yaml|wide")
return command
}
@@ -325,7 +337,10 @@ func NewApplicationSetListCommand(clientOpts *argocdclient.ClientOptions) *cobra
// NewApplicationSetDeleteCommand returns a new instance of an `argocd appset delete` command
func NewApplicationSetDeleteCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var noPrompt bool
var (
noPrompt bool
wait bool
)
command := &cobra.Command{
Use: "delete",
Short: "Delete one or more ApplicationSets",
@@ -340,7 +355,8 @@ func NewApplicationSetDeleteCommand(clientOpts *argocdclient.ClientOptions) *cob
c.HelpFunc()(c, args)
os.Exit(1)
}
conn, appIf := headless.NewClientOrDie(clientOpts, c).NewApplicationSetClientOrDie()
acdClient := headless.NewClientOrDie(clientOpts, c)
conn, appIf := acdClient.NewApplicationSetClientOrDie()
defer utilio.Close(conn)
isTerminal := isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())
numOfApps := len(args)
@@ -373,6 +389,20 @@ func NewApplicationSetDeleteCommand(clientOpts *argocdclient.ClientOptions) *cob
if confirm || confirmAll {
_, err := appIf.Delete(ctx, &appsetDeleteReq)
errors.CheckError(err)
if wait {
_, getErr := appIf.Get(ctx, &applicationset.ApplicationSetGetQuery{
Name: appSetName, AppsetNamespace: appSetNs,
})
if getErr == nil {
appEventCh := acdClient.WatchApplicationSetWithRetry(ctx, appSetQualifiedName, "")
for appEvent := range appEventCh {
if appEvent != nil && appEvent.Type == k8swatch.Deleted {
break
}
}
}
}
fmt.Printf("applicationset '%s' deleted\n", appSetQualifiedName)
} else {
fmt.Println("The command to delete '" + appSetQualifiedName + "' was cancelled.")
@@ -381,6 +411,7 @@ func NewApplicationSetDeleteCommand(clientOpts *argocdclient.ClientOptions) *cob
},
}
command.Flags().BoolVarP(&noPrompt, "yes", "y", false, "Turn off prompting to confirm cascaded deletion of Application resources")
command.Flags().BoolVar(&wait, "wait", false, "Wait until deletion of the applicationset(s) completes")
return command
}
@@ -462,7 +493,7 @@ func printAppSetSummaryTable(appSet *arogappsetv1.ApplicationSet) {
)
if syncPolicy != nil && syncPolicy.IsAutomatedSyncEnabled() {
syncPolicyStr = "Automated"
if syncPolicy.Automated.Prune {
if syncPolicy.Automated.GetPrune() {
syncPolicyStr += " (Prune)"
}
} else {
@@ -478,6 +509,31 @@ func printAppSetConditions(w io.Writer, appSet *arogappsetv1.ApplicationSet) {
}
}
func isApplicationSetResourcesUpToDate(appSet *arogappsetv1.ApplicationSet) bool {
for _, c := range appSet.Status.Conditions {
if c.Type == arogappsetv1.ApplicationSetConditionResourcesUpToDate {
return c.Status == arogappsetv1.ApplicationSetConditionStatusTrue
}
}
return false
}
func waitForApplicationSetResourcesUpToDate(ctx context.Context, acdClient argocdclient.Client, appSetName string) error {
appEventCh := acdClient.WatchApplicationSetWithRetry(ctx, appSetName, "")
for appEvent := range appEventCh {
if appEvent == nil {
continue
}
if appEvent.Type == k8swatch.Deleted {
return fmt.Errorf("ApplicationSet %q was deleted before reaching ResourcesUpToDate", appSetName)
}
if isApplicationSetResourcesUpToDate(&appEvent.ApplicationSet) {
return nil
}
}
return fmt.Errorf("watch stream closed for ApplicationSet %q before reaching ResourcesUpToDate", appSetName)
}
func hasAppSetChanged(appReq, appRes *arogappsetv1.ApplicationSet, upsert bool) bool {
// upsert==false, no change occurred from create command
if !upsert {

View File

@@ -1,6 +1,8 @@
package commands
import (
"context"
"errors"
"io"
"os"
"testing"
@@ -8,10 +10,94 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/watch"
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
)
// TestAppSetDeleteWaitFlow verifies that when --wait is used and the appset has
// finalizers (still exists after Delete), the delete command watches for Deleted.
func TestAppSetDeleteWaitFlow(t *testing.T) {
appSetEventsCh := make(chan *v1alpha1.ApplicationSetWatchEvent, 1)
go func() {
defer close(appSetEventsCh)
appSetEventsCh <- &v1alpha1.ApplicationSetWatchEvent{
Type: watch.Added,
ApplicationSet: v1alpha1.ApplicationSet{ObjectMeta: metav1.ObjectMeta{Name: "test-appset"}},
}
appSetEventsCh <- &v1alpha1.ApplicationSetWatchEvent{Type: watch.Deleted}
}()
receivedDeleted := false
for appEvent := range appSetEventsCh {
if appEvent != nil && appEvent.Type == watch.Deleted {
receivedDeleted = true
break
}
}
assert.True(t, receivedDeleted, "wait loop should receive Deleted event from watch")
}
// TestAppSetCreateWaitFlow verifies that when --wait is used, the create command
// waits for ResourcesUpToDate from the watch before completing.
func TestAppSetCreateWaitFlow(t *testing.T) {
fakeClient := &fakeAcdClient{}
ctx := context.Background()
err := waitForApplicationSetResourcesUpToDate(ctx, fakeClient, "test-appset")
require.NoError(t, err)
}
func TestAppSetCreateWaitDeletedError(t *testing.T) {
appSetEventsCh := make(chan *v1alpha1.ApplicationSetWatchEvent, 1)
go func() {
defer close(appSetEventsCh)
appSetEventsCh <- &v1alpha1.ApplicationSetWatchEvent{Type: watch.Deleted}
}()
var err error
for appEvent := range appSetEventsCh {
if appEvent == nil {
continue
}
if appEvent.Type == watch.Deleted {
err = errors.New("ApplicationSet was deleted before reaching ResourcesUpToDate")
break
}
}
require.Error(t, err)
assert.Contains(t, err.Error(), "deleted before reaching ResourcesUpToDate")
}
func TestIsApplicationSetResourcesUpToDate(t *testing.T) {
t.Run("returns true when ResourcesUpToDate is True", func(t *testing.T) {
appSet := &v1alpha1.ApplicationSet{
Status: v1alpha1.ApplicationSetStatus{
Conditions: []v1alpha1.ApplicationSetCondition{
{Type: v1alpha1.ApplicationSetConditionResourcesUpToDate, Status: v1alpha1.ApplicationSetConditionStatusTrue},
},
},
}
assert.True(t, isApplicationSetResourcesUpToDate(appSet))
})
t.Run("returns false when ResourcesUpToDate is False", func(t *testing.T) {
appSet := &v1alpha1.ApplicationSet{
Status: v1alpha1.ApplicationSetStatus{
Conditions: []v1alpha1.ApplicationSetCondition{
{Type: v1alpha1.ApplicationSetConditionResourcesUpToDate, Status: v1alpha1.ApplicationSetConditionStatusFalse},
},
},
}
assert.False(t, isApplicationSetResourcesUpToDate(appSet))
})
t.Run("returns false when no conditions", func(t *testing.T) {
appSet := &v1alpha1.ApplicationSet{}
assert.False(t, isApplicationSetResourcesUpToDate(appSet))
})
}
func TestPrintApplicationSetNames(t *testing.T) {
output, _ := captureOutput(func() error {
appSet := &v1alpha1.ApplicationSet{
@@ -174,7 +260,7 @@ func TestPrintAppSetSummaryTable(t *testing.T) {
appSetTemplateSpecSyncPolicy := baseAppSet.DeepCopy()
appSetTemplateSpecSyncPolicy.Spec.Template.Spec.SyncPolicy = &v1alpha1.SyncPolicy{
Automated: &v1alpha1.SyncPolicyAutomated{
SelfHeal: true,
SelfHeal: new(true),
},
}
@@ -184,7 +270,7 @@ func TestPrintAppSetSummaryTable(t *testing.T) {
}
appSetBothSyncPolicies.Spec.Template.Spec.SyncPolicy = &v1alpha1.SyncPolicy{
Automated: &v1alpha1.SyncPolicyAutomated{
SelfHeal: true,
SelfHeal: new(true),
},
}

Some files were not shown because too many files have changed in this diff Show More