Compare commits

...

463 Commits

Author SHA1 Message Date
dependabot[bot]
8126886e25 chore(deps): bump node from 20 to 24
Bumps node from 20 to 24.

---
updated-dependencies:
- dependency-name: node
  dependency-version: '24'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-18 03:23:56 +00:00
rumstead
8ede222650 fix(goreleaser): add darwin with CGO enabled and remove static to gorelease (#23457)
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
2025-06-17 20:01:00 +00:00
Alexandre Gaudreault
e25123b63d chore(test): add e2e tests for gitops-engine (#23304)
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-06-17 20:34:02 +02:00
Yann Soubeyrand
d6efb9e538 chore: move OIDC PKCE support from UI to backend (#21729)
Signed-off-by: Yann Soubeyrand <8511577+yann-soubeyrand@users.noreply.github.com>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-06-17 18:18:24 +00:00
Flávio Roberto Santos
9849d2743b docs: Explain repo definition for source hydrators (#23454)
Signed-off-by: Flávio Santos <flavios@spotify.com>
Co-authored-by: Flávio Santos <flavios@spotify.com>
2025-06-17 13:33:45 -04:00
Matthieu MOREL
8b2560497a chore(lint): enable filepathJoin rule from go-critic (#23453)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-17 13:32:44 -04:00
Tanner Stirrat
2fc05c58e7 docs: Docs usage fix (#23450)
Signed-off-by: Tanner Stirrat <tstirrat@gmail.com>
2025-06-17 12:23:36 -04:00
Oleksandr Tkachenko
590d0cda64 fix(ui): make Name column wider (argoproj#21080) (#21375)
Signed-off-by: Oleksandr Tkachenko <korsar182@gmail.com>
2025-06-17 11:51:05 -04:00
Matthieu MOREL
fa25f278c0 chore(lint): enable sloppyReassign rule from go-critic (#23443)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-17 11:46:50 -04:00
Bob Du
127293dcc7 docs: Clarify Google Directory API scope requirements in documentation (#23386)
Signed-off-by: Bob Du <i@bobdu.cc>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Nitish Kumar <justnitish06@gmail.com>
2025-06-17 15:23:51 +00:00
Codey Jenkins
b39e3a8d1e chore: initial support for tilt based development (#22337) (#23002)
Signed-off-by: Codey Jenkins <FourFifthsCode@users.noreply.github.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-17 11:19:50 -04:00
Mason Liu
531b79ad8d fix: #23041 Add resource support to 'argocd proj role add-policy/remove-policy' (#23213)
Signed-off-by: Mason Liu <fuyin.liu@fmr.com>
2025-06-17 10:55:27 -04:00
dependabot[bot]
fb0a89864c chore(deps): bump github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus from 1.0.1 to 1.1.0 (#23441)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-17 10:42:51 -04:00
Eric Fortin
0893d7349d docs: regroup generators reference fixes #23439 (#23440)
Signed-off-by: Eric Fortin <eric.fortin2@gmail.com>
2025-06-17 10:42:17 -04:00
Kanika Rana
a3ef471913 chore(finalizers): remove hardcoding of application and applicationset finalizers (#23420)
Signed-off-by: Kanika Rana <krana@redhat.com>
2025-06-17 01:56:58 -10:00
Cheng Fang
25fc5d2b0c chore(cli): fix argocd admin repo command usage docs and examples (#23375)
Signed-off-by: Cheng Fang <cfang@redhat.com>
2025-06-16 22:51:13 -04:00
Michael Crenshaw
c11b36d455 docs(cli): improve argocd actions run docs (#23376)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-16 22:49:43 -04:00
Kunho Lee
3ff30dfac1 fix: add optional chaining before access to the targetRevision field (#23397)
Signed-off-by: daengdaengLee <gunho1020@gmail.com>
2025-06-16 22:48:52 -04:00
Alexandre Gaudreault
1b6c8237d3 chore(docs): prepare for new release (#23437)
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-06-16 22:46:52 -04:00
Regina Voloshin
964f26901c feat: Add GitHub API rate limit metrics (#22864)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
Signed-off-by: Regina Voloshin <regina.voloshin@codefresh.io>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-06-17 01:41:38 +00:00
Cayde6
98ca41125c feat: add metric for sync durations(#11675) (#18474)
Signed-off-by: Jack-R-lantern <tjdfkr2421@gmail.com>
2025-06-16 19:00:49 -04:00
Keith Chong
2c53861edb feat: Polish off UI changes for OCI support (#21685) (#22410)
Signed-off-by: Keith Chong <kykchong@redhat.com>
2025-06-16 18:58:21 -04:00
Matthieu MOREL
54501c05a8 chore(lint): enable builtinShadow rule from go-critic (#23430)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-16 21:20:57 +00:00
rumstead
0b8d018fdf fix(goreleaser): add darwin with CGO enabled to goreleaser (#23433)
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
2025-06-16 17:08:52 -04:00
Michael Crenshaw
91e5f954a3 fix(hydrator): incorrect json tag (#23432)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-16 20:31:43 +00:00
Michael Crenshaw
30c325d952 chore(refactor): simplify maps util (#23431)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-16 16:29:45 -04:00
Matthieu MOREL
ede2b32aea chore(lint): enable ptrToRefParam rule from go-critic (#23424)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-16 19:28:57 +00:00
Michael Crenshaw
061d5992da chore(refactor): replace trivial function w/ standard lib (#23429)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-16 15:23:39 -04:00
Matthieu MOREL
1203ad0660 chore(lint): enable-all govet rules by default (#23426)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-16 19:03:03 +00:00
Matthieu MOREL
4731c61d7a chore(lint): enable evalOrder rule from go-critic (#23422)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-16 14:04:05 -04:00
Matthieu MOREL
7cc360e5af chore(lint): enable mapKey rule from go-critic (#23417)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-16 14:03:28 -04:00
Peter Jiang
df5ff1f746 fix(doc): Fix typo in SSA doc (#23421)
Signed-off-by: Peter Jiang <35584807+pjiang-dev@users.noreply.github.com>
2025-06-16 16:45:16 +00:00
Matthieu MOREL
6b24fcb32c chore(lint): enable typeDefFirst rule from go-critic (#23414)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-16 16:09:08 +00:00
Michael Crenshaw
114693dcc2 chore(lint): enable typeSwitchVar linter (#23391)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-16 15:02:32 +00:00
Matthieu MOREL
10fa1aa8c8 chore(lint): enable unnecessaryBlock rule from go-critic (#23404)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-16 10:00:55 -04:00
Oliver Gondža
28e871e7e2 chore(sonar): Fix sonar warnings in applicationset/generators/duck_type.go (#23211)
Signed-off-by: Oliver Gondža <ogondza@gmail.com>
Co-authored-by: Nitish Kumar <justnitish06@gmail.com>
2025-06-16 08:59:35 -04:00
Matthieu MOREL
a91a6594a1 chore(lint): enable regexpSimplify rule from go-critic (#23405)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-16 08:55:05 -04:00
Matthieu MOREL
52ad029110 chore(lint): enable typeUnparen rule from go-critic (#23406)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-16 08:54:28 -04:00
Matthieu MOREL
fd48c47cf9 chore(lint): enable typeAssertChain rule from go-critic (#23407)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-16 09:28:20 +02:00
Matthieu MOREL
b6e90ea92c chore(lint): enable sprintfQuotedString rule from go-critic (#23401)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-15 16:33:20 -04:00
Matthieu MOREL
c6ebc19c1f chore(lint): enable emptyStringTest rule from go-critic (#23400)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-15 20:25:12 +00:00
github-actions[bot]
c2e93a3e95 [Bot] docs: Update Snyk report (#23394)
Signed-off-by: CI <ci@argoproj.com>
Co-authored-by: CI <ci@argoproj.com>
2025-06-15 20:19:27 +00:00
Matthieu MOREL
79c75876a8 chore(lint): enable httpNoBody rule from go-critic (#23399)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-15 16:11:38 -04:00
Jennifer Weir
2801a11efc fix(health-check): StorageCluster.ocs.openshift.io (#23393)
Signed-off-by: Jennifer Weir <contact@jenniferpweir.com>
2025-06-14 18:08:44 -04:00
Michael Crenshaw
64198e8042 feat(ci): don't cancel-in-progress on master (#23392)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-14 17:33:59 -04:00
Peter Jiang
dc1d148a5d feat: add SSA field manager migration options (#23337)
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
Signed-off-by: Peter Jiang <35584807+pjiang-dev@users.noreply.github.com>
2025-06-13 21:58:07 +00:00
Mike Ng
7a064000a0 fix(appset): add default retry limit for operations triggered via RollingSync (#20428) (#23335)
Signed-off-by: Mike Ng <ming@redhat.com>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-06-13 21:14:02 +00:00
Michael Crenshaw
96fd06165e fix(hydrator): split commit subject and body, make author one string (#23389)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-13 17:00:29 -04:00
Michael Crenshaw
8c6f35bf5c chore: enforce JS bundle size limit (#12922)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-13 16:53:02 -04:00
Blake Pettersson
2ae9f43410 chore: upgrade mockery (#23387)
Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
2025-06-13 19:58:11 +00:00
Christian Hernandez
d14ba140d1 feat(cli): Adding whoami alias (#23385)
Signed-off-by: Christian Hernandez <christian@chernand.io>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
2025-06-13 15:37:43 -04:00
Michael Crenshaw
81ae77a4ad feat(hydrator): commit tracing (#19441) (#23361)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-13 15:14:03 -04:00
Michael Crenshaw
d33b9b98ba chore(lint): enable nestingReduce linter (#23378)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-13 13:43:16 -04:00
Peter Jiang
1df47e9aa4 chore: upgrade k8s to 1.33.1 (#23362)
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
2025-06-13 17:06:19 +00:00
Hazel Sudzilouski
44fce0e478 fix: add fatal timeout upgrade with SIGKILL to ARGO_EXEC_TIMEOUT (closes #20785, #18478) (#22713)
Signed-off-by: Hazel Sudzilouski <dsudzilouski@olin.edu>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-06-13 15:59:45 +00:00
fprovencherdrw
8f1f5c7234 feat(health): add Logstash resource customization (#22028)
Signed-off-by: Francis Provencher <fprovencher@drw.com>
2025-06-13 11:57:56 -04:00
Michael Crenshaw
6174b94d6a fix(test): race condition in kubectl metrics (#23382) (#23383)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-13 15:41:43 +00:00
Marcus Söderberg
00ee32f7f5 feat: optionally propagate node labels to application pod view (#15274) (#23260)
Signed-off-by: Marcus Söderberg <msoderb@gmail.com>
Co-authored-by: Linghao Su <slh001@live.cn>
2025-06-13 11:19:27 -04:00
Jonathan Gonzalez V.
f4edcf7717 feat: add custom health check for CloudNativePG (#22802)
Signed-off-by: Jonathan Gonzalez V. <jonathan.abdiel@gmail.com>
2025-06-13 11:08:27 -04:00
Joe Bowbeer
6d25734852 fix: typo in native-oci-support.md (#23379)
Signed-off-by: Joe Bowbeer <joe.bowbeer@gmail.com>
2025-06-13 08:59:59 +02:00
Jennifer Weir
6c299bc783 feat(health-check): add resource_customizations for ocs.openshift.io (#23173)
Signed-off-by: Jennifer Weir <contact@jenniferpweir.com>
2025-06-12 21:27:56 -04:00
Yusuke Abe
a2152a1216 feat: Implement healthcheck gateway api (#20986) (#22855)
Signed-off-by: chansuke <moonset20@gmail.com>
2025-06-12 16:44:22 -04:00
mikebordon
d4bdabd64d fix(server): Propagate useAzureWorkloadIdentity flag from during repo validation (#23348) (#23358)
Signed-off-by: Mike Bordon <mikebordon@gmail.com>
2025-06-12 12:56:47 -04:00
Blake Pettersson
6e972e436a fix: properly handle shutdown signal for admin dashboard (#23231)
Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
2025-06-12 05:50:13 -10:00
Michael Crenshaw
7814790ff3 fix(repo-server): sort images (#23372)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-12 11:28:45 -04:00
dependabot[bot]
ee92cf56f2 chore(deps): bump softprops/action-gh-release from 2.3.0 to 2.3.2 (#23351)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-12 08:22:38 -04:00
Cheng Fang
8b567c99b4 chore(cli): fix argocd repo command usage docs and description (#23364)
Signed-off-by: Cheng Fang <cfang@redhat.com>
2025-06-12 08:21:49 -04:00
Dillen Padhiar
5091f9a3f7 feat: remove suspended state from numaproj crds (#23359)
Signed-off-by: Dillen Padhiar <dillen_padhiar@intuit.com>
2025-06-12 07:35:58 -04:00
dependabot[bot]
c7a0fa3a8c chore(deps): bump gitlab.com/gitlab-org/api/client-go from 0.129.0 to 0.130.1 (#23365)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-12 11:25:19 +00:00
Michael Crenshaw
2bf3f6850e chore(lint): enable more gocritic linters (#23328)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-11 23:50:02 -04:00
dependabot[bot]
046b9e7d97 chore(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azidentity from 1.10.0 to 1.10.1 (#23350)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-11 23:45:52 -04:00
dependabot[bot]
dbd8009f18 chore(deps): bump github.com/go-git/go-git/v5 from 5.16.1 to 5.16.2 (#23341)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-11 13:47:08 -04:00
dependabot[bot]
0a8a7e246f chore(deps): bump github.com/ktrysmt/go-bitbucket from 0.9.85 to 0.9.86 (#23349)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-11 12:11:25 -04:00
dependabot[bot]
7496ede7c2 chore(deps): bump softprops/action-gh-release from 2.2.2 to 2.3.0 (#23340)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-10 09:07:41 -04:00
Michael Crenshaw
7ee59d02b6 docs: document syncPolicy.automated.enable field (#23332)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-09 17:50:18 +00:00
Saptadip Sarkar
463155b8b4 docs: Update 2.14-3.0.md (#23314)
Signed-off-by: Saptadip Sarkar <12973082+saptadip@users.noreply.github.com>
2025-06-09 11:34:34 -04:00
J3m3
5dba0648f3 docs: clean up ci_automation.md for correctness and clarity (#23329)
Signed-off-by: Jesung Yang <y.j3ms.n@gmail.com>
2025-06-09 11:33:11 -04:00
Michael Crenshaw
949c9eabd3 feat(commit-server): use os.Root for traversal protection (#22956)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-09 10:09:21 -04:00
Dan Rice
8fde8d0a4b fix(ui): Improve light/dark theme selector label (#22958)
Signed-off-by: Dan Rice <dan@dnrce.com>
2025-06-09 10:54:41 +03:00
dependabot[bot]
2093179488 chore(deps): bump github.com/casbin/casbin/v2 from 2.106.0 to 2.107.0 (#23322)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-09 01:06:53 -04:00
sivchari
61b3ea1187 fix: context cancellation handling (#22824)
Signed-off-by: sivchari <shibuuuu5@gmail.com>
2025-06-08 14:10:46 -04:00
Kim Brose
80a194af85 docs: Fix section nesting in webhook.md (#23278)
Signed-off-by: Kim Brose <2803622+HarHarLinks@users.noreply.github.com>
2025-06-08 14:08:18 -04:00
Regina Voloshin
2e1e3162e5 docs: Add docs for local chain e2e tests run (#23319)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
2025-06-08 11:44:41 -04:00
Michael Crenshaw
0fa3c3d67d chore(lint): enable tparallel linter (#23318)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-08 15:10:55 +02:00
github-actions[bot]
68c8b99270 [Bot] docs: Update Snyk report (#23315)
Signed-off-by: CI <ci@argoproj.com>
Co-authored-by: CI <ci@argoproj.com>
2025-06-07 20:47:56 -04:00
ABBOUD Moncef
01a882d429 fix: do not fail on manifest-like yaml #21934 (#22043)
Signed-off-by: Moncef Abboud <moncef.abboud95@gmail.com>
2025-06-07 14:51:18 -04:00
Philippe Merle
edf36831ab fix: Add metadata labels to all NetworkPolicy resources (#23313)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Signed-off-by: Philippe Merle <philippe.merle@inria.fr>
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Kim Brose <2803622+HarHarLinks@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Kim Brose <2803622+HarHarLinks@users.noreply.github.com>
2025-06-07 13:05:41 -04:00
Michael Crenshaw
7915002382 fix(server): race condition in revoked token logic (#23311) (#23312)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-06 16:49:59 -04:00
Kim Brose
43ce82801d docs: spelling, formatting, etc updates (#23306)
Signed-off-by: Kim Brose <2803622+HarHarLinks@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-06 15:37:59 -04:00
Michael Crenshaw
36f91a0231 fix(metrics): populate dest_server label (#23246) (#23269)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-06 13:25:29 -04:00
dependabot[bot]
47326bda6d chore(deps): bump google.golang.org/grpc from 1.72.2 to 1.73.0 (#23292)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-06 13:08:23 -04:00
Michael Crenshaw
8010b4f733 chore: bump gitops-engine for error wrapping (#23282)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-06 11:51:04 -04:00
Blake Pettersson
18c4d9d568 feat: oci support (Beta) (#18646)
Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-06 13:27:02 +02:00
Ville Vesilehto
109cd6c382 fix(tls): validate RSA keys before marshaling (#23295)
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
2025-06-06 13:05:41 +02:00
Ville Vesilehto
e1195fd931 chore: upgrade Go from 1.24.3 to 1.24.4 (#23287)
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
2025-06-06 12:46:46 +02:00
dependabot[bot]
41a4cd3032 chore(deps): bump golang.org/x/sync from 0.14.0 to 0.15.0 (#23290)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-06 04:25:30 +00:00
dependabot[bot]
ee45d0fc1b chore(deps): bump golang.org/x/time from 0.11.0 to 0.12.0 (#23288)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-06 04:25:15 +00:00
dependabot[bot]
d9b102bea0 chore(deps): bump golang.org/x/net from 0.40.0 to 0.41.0 (#23289)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-06 04:24:39 +00:00
Kim Brose
fc3c929cea docs: Fix notice blocks in reconcile.md (#23277)
Signed-off-by: Kim Brose <2803622+HarHarLinks@users.noreply.github.com>
2025-06-05 11:57:36 -04:00
KoB
9472273a1b feat(health-check): Add resource_customizations for karpenter (#23139)
Signed-off-by: 김병준 <kingbj0429@gmail.com>
2025-06-05 14:22:39 +00:00
Ragul Shanmugarajan
b3e72ac3e6 docs: Add replace syncOption in application.yaml (#23274)
Signed-off-by: Ragul Shanmugarajan <96675784+ragul-engg@users.noreply.github.com>
2025-06-05 08:58:19 -04:00
dependabot[bot]
9050798094 chore(deps): bump github.com/alicebob/miniredis/v2 from 2.34.0 to 2.35.0 (#23271)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-05 07:48:50 -04:00
dependabot[bot]
23ab5fc23c chore(deps): bump github.com/go-git/go-git/v5 from 5.16.0 to 5.16.1 (#23270)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-05 07:48:25 -04:00
Michael Crenshaw
30a0088c84 chore: enable lint for unused private fields (#23242)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-05 07:47:55 -04:00
Blake Pettersson
f532299f7c fix: parse project with applicationset resource (#23252)
Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
2025-06-04 23:38:24 +02:00
github-actions[bot]
1ecc561d9e [Bot] docs: Update Snyk report (#23265)
Signed-off-by: CI <ci@argoproj.com>
Co-authored-by: CI <ci@argoproj.com>
2025-06-04 13:24:25 -04:00
dependabot[bot]
7246c0246f chore(deps): bump github.com/expr-lang/expr from 1.17.4 to 1.17.5 (#23248)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-04 12:56:48 -04:00
Oliver Gondža
7bb7385e46 fix(snyk-report): Sort analyzed released, add master (#23250)
Signed-off-by: Oliver Gondža <ogondza@gmail.com>
2025-06-04 12:52:51 -04:00
Jethro Lee (이드로)
eb794b7db9 feat(ui): set validate=false for "disable autosync" request during rollback via ui (#22898) (#23101)
Signed-off-by: 이드로 (Jethro Lee) <dlemfh96@gmail.com>
2025-06-04 10:43:35 -04:00
Eric Fortin
e691ee35b4 docs: improved applicationset doc when deployed using helm. addresses #23155 (#23256)
Signed-off-by: Eric Fortin <eric.fortin2@gmail.com>
2025-06-04 07:52:08 -06:00
Kim Brose
e89e05486d docs: Fix typos (#23259)
Signed-off-by: Kim Brose <2803622+HarHarLinks@users.noreply.github.com>
2025-06-04 07:50:30 -06:00
Bryan Montaño Estrada
9df2fd9a67 docs: Added eSave to USERS.md (#23258)
Signed-off-by: Bryan <bryan.montano@esave.es>
2025-06-04 08:24:28 -04:00
dependabot[bot]
8679549c38 chore(deps): bump github.com/casbin/casbin/v2 from 2.105.0 to 2.106.0 (#23247)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-04 08:19:51 -04:00
Revital Barletz
ae6e35976d docs: update the defaultAppResyncPeriodJitter value to 60 (#23251)
Signed-off-by: Revital Barletz <revitalbarletz@gmail.com>
2025-06-04 11:05:37 +02:00
Eunji
0e9519314b feat(ui): allows more convenient sorting of repository. (#19829)
Signed-off-by: EunJiJung <bianbbc87@gmail.com>
Signed-off-by: Eunji <129590633+bianbbc87@users.noreply.github.com>
Co-authored-by: Suraj yadav <harrypotter1108@gmail.com>
2025-06-03 16:09:59 -04:00
Oliver Gondža
4b1bd1852f fix(snyk-report): Improve calculation of latest patch release (#23223)
Signed-off-by: Oliver Gondža <ogondza@gmail.com>
2025-06-03 17:42:15 +00:00
Jonathan Ballet
4b866292e5 docs: Fix formatting in the "high-availability" documentation page (#23235)
Signed-off-by: Jonathan Ballet <jon@multani.info>
2025-06-03 15:31:23 +02:00
dependabot[bot]
5290de32b8 chore(deps): bump library/golang from 4c0a181 to 81bf592 in /test/remote (#23220)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-03 07:46:22 -04:00
Michael Crenshaw
2c3a452fd7 chore: remove unused Trunc function (#23232)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-03 08:27:43 +02:00
sivchari
ea97dec642 fix: KubeVersion passed to helm template is incorrectly (#22650)
Signed-off-by: sivchari <shibuuuu5@gmail.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-02 20:53:51 +00:00
Jagpreet Singh Tamber
c0c6abedc4 fix: #23100 Change workloadidentity token cache expiry based on token expiry. (#23133)
Signed-off-by: Jagpreet Singh Tamber <jagpreetstamber@gmail.com>
2025-06-02 20:51:30 +00:00
dependabot[bot]
b39ca155dc chore(deps): bump github.com/bradleyfalzon/ghinstallation/v2 from 2.15.0 to 2.16.0 (#23221)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-02 07:05:40 -06:00
Nitish Kumar
81ac6216a6 chore: update release notes blog post link to v3.0 (#23222)
Signed-off-by: Nitish Kumar <justnitish06@gmail.com>
2025-06-02 09:42:15 +02:00
Kunho Lee
76f80b375c fix: #22879 override default variables in Makefile when your env is local Mac (#23182)
Signed-off-by: daengdaengLee <gunho1020@gmail.com>
2025-06-02 12:20:36 +05:30
dependabot[bot]
fb40acdd79 chore(deps): bump ossf/scorecard-action from 2.4.1 to 2.4.2 (#23217)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-01 22:10:00 -06:00
Andrew Block
4a15925edc feat: improve Helm documentation (#22859)
Signed-off-by: Andrew Block <andy.block@gmail.com>
2025-05-31 14:30:43 +02:00
dependabot[bot]
234c73a688 chore(deps): bump library/golang from e84f2e8 to 4c0a181 in /test/remote (#23209)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-30 08:00:54 -04:00
Michael Crenshaw
2e3f9eb1c0 chore(ci): pin tj-actions/changed-files to v46.0.5 (#23206)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-30 07:32:41 -04:00
Michael Crenshaw
5509dd8646 test(server): handle string groups claim (#22973) (#23208)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-29 20:17:20 +00:00
dependabot[bot]
b9cf44b584 chore(deps): bump library/golang from 1bcf884 to e84f2e8 in /test/remote (#23106)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-29 12:40:25 -07:00
Michael Crenshaw
7fda067767 fix(server): avoid unnecessary claims restrictions (#22973) (#23202)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-29 18:57:12 +00:00
Lehlogonolo N. Masubelele
f43523a69e docs: Bulk typo fix (#23144) 2025-05-29 12:54:40 -06:00
Michael Crenshaw
54a45c4f89 chore: disable gitpod (#23201)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-29 12:54:21 -06:00
Michael Crenshaw
33959d0605 chore(ci): disable dependabot for ui-test (#23200)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-29 12:54:07 -06:00
Luke
7d6604404f feat(health): Implement spinkube SpinApp CRD health checks (#21896)
Signed-off-by: lukepatrick <lukephilips@gmail.com>
2025-05-29 11:27:19 -06:00
Christian Hernandez
1be1d1c0ae chore: setting up 3.1 release champion and approver (#23203)
Signed-off-by: Christian Hernandez <christian@chernand.io>
2025-05-29 15:42:09 +00:00
Dillen Padhiar
ddb1021440 feat: improve numa actions (#22835)
Signed-off-by: Dillen Padhiar <dillen_padhiar@intuit.com>
2025-05-29 09:24:32 -06:00
dependabot[bot]
b8051c60a9 chore(deps): bump github.com/go-logr/logr from 1.4.2 to 1.4.3 (#23194)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-29 07:28:52 -06:00
Michael Crenshaw
3bbbac4bb9 fix(hydrator): increase max msg size (#23190)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-28 21:09:13 +00:00
dependabot[bot]
7735b743b3 chore(deps): bump github.com/olekukonko/tablewriter from 1.0.6 to 1.0.7 (#23174)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-28 09:13:53 -06:00
dependabot[bot]
ee3752df70 chore(deps): bump github.com/expr-lang/expr from 1.17.3 to 1.17.4 (#23175)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-28 09:12:02 -06:00
dependabot[bot]
8ad0e22bf1 chore(deps): bump docker/build-push-action from 6.17.0 to 6.18.0 (#23179)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-28 09:11:03 -06:00
RyotaK
a5b4041a79 Merge commit from fork
Fix shadowed variable name

Signed-off-by: Ry0taK <49341894+Ry0taK@users.noreply.github.com>
2025-05-28 08:20:48 -06:00
Aaron Hoffman
18ce5c271f feat: Add images to resources in sync result #20896 (#20954)
Signed-off-by: Aaron Hoffman <31711338+Aaron-9900@users.noreply.github.com>
2025-05-27 19:58:28 +00:00
dependabot[bot]
10abed751e chore(deps): bump ossf/scorecard-action from 2.4.0 to 2.4.1 (#23149)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-27 11:53:24 -06:00
Pavel Skuratovich
81f3843f04 docs: fix a typo in config-management-plugins.md (#23172)
Signed-off-by: Pavel Skuratovich <chupaka@gmail.com>
2025-05-27 10:21:17 -06:00
Poojan Savani
65464d8b77 feat(health): OpenTelemetryCollector CRD Healthcheck (#23156)
Signed-off-by: poojan <poojan@hasura.io>
2025-05-27 09:08:41 -06:00
dependabot[bot]
ad6f0afa57 chore(deps): bump SonarSource/sonarqube-scan-action from 4.2.1 to 5.2.0 (#23164)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-27 08:18:10 -06:00
Eric Fortin
6ef971330a fix(test): #23137 removed left over file that breaks subsequent make test run. (#23138)
Signed-off-by: Eric Fortin <eric.fortin2@gmail.com>
2025-05-27 08:13:06 -06:00
dependabot[bot]
3de278ef85 chore(deps): bump tj-actions/changed-files from 3981e4f74104e7a4c67a835e1e5dd5d9eb0f0a57 to c6634ca281a9fc05b03bee224ba00910cb78ab6e (#23165)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-27 01:00:54 -04:00
dependabot[bot]
1ff739dccb chore(deps): bump library/busybox from 3308bdf to f64ff79 in /test/e2e/multiarch-container (#23145)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-27 01:00:27 -04:00
dependabot[bot]
2f0bde61b5 chore(deps): bump google.golang.org/grpc from 1.72.1 to 1.72.2 (#23161)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-27 00:57:26 -04:00
dependabot[bot]
a5012404fb chore(deps): bump goreleaser/goreleaser-action from 6.1.0 to 6.3.0 (#23163)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-27 00:56:55 -04:00
dependabot[bot]
a2ff605212 chore(deps): bump slsa-framework/slsa-github-generator from 2.0.0 to 2.1.0 (#23166)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-27 00:56:20 -04:00
dependabot[bot]
1d44046141 chore(deps): bump actions/setup-go from 5.2.0 to 5.5.0 (#23151)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 18:39:39 -06:00
dependabot[bot]
d076bfa074 chore(deps-dev): bump @babel/core from 7.7.2 to 7.27.1 in /ui (#23148)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 10:24:03 -04:00
dependabot[bot]
45f12f2676 chore(deps): bump softprops/action-gh-release from 2.2.1 to 2.2.2 (#23150)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 10:20:27 -04:00
dependabot[bot]
8c23cbdf13 chore(deps): bump selenium-webdriver from 4.32.0 to 4.33.0 in /ui-test (#23147)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 10:19:57 -04:00
dependabot[bot]
e5ee3e42d2 chore(deps-dev): bump mocha from 11.4.0 to 11.5.0 in /ui-test (#23146)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 10:19:37 -04:00
dependabot[bot]
e9863708b6 chore(deps): bump docker/setup-buildx-action from 3.8.0 to 3.10.0 (#23152)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 10:18:06 -04:00
dependabot[bot]
c63885298c chore(deps): bump actions/download-artifact from 4.1.8 to 4.3.0 (#23153)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 10:17:40 -04:00
dependabot[bot]
0205eafa8e chore(deps-dev): bump @types/jest from 29.5.12 to 29.5.14 in /ui (#23117)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-25 14:56:25 -04:00
Matthieu MOREL
b6d9d6dd33 chore: enable exptostd linter (#23136)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-05-24 08:13:47 -06:00
dependabot[bot]
df9ea61424 chore(deps): bump library/busybox from 37f7b37 to 3308bdf in /test/e2e/multiarch-container (#23119)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 09:18:38 -07:00
dependabot[bot]
f138b35889 chore(deps): bump tj-actions/changed-files from bab30c2299617f6615ec02a68b9a40d10bd21366 to 3981e4f74104e7a4c67a835e1e5dd5d9eb0f0a57 (#23121)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-23 15:02:30 +00:00
dependabot[bot]
6dc031987f chore(deps): bump docker/setup-qemu-action from 3.2.0 to 3.6.0 (#23120)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 10:24:02 -04:00
dependabot[bot]
81c17cbcdd chore(deps): bump docker/build-push-action from 6.10.0 to 6.17.0 (#23122)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 10:20:46 -04:00
dependabot[bot]
2ed3ebe807 chore(deps): bump actions/cache from 4.2.0 to 4.2.3 (#23123)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 10:20:15 -04:00
Thiago Perrotta
47213a4392 docs(reconcile.md): fix command example (#23132)
Signed-off-by: Thiago Perrotta <tbperrotta@gmail.com>
2025-05-23 09:17:29 -04:00
dependabot[bot]
cefb62292d chore(deps): bump codecov/test-results-action from 1.0.1 to 1.1.1 (#23124)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 13:13:08 +02:00
Alexandre Gaudreault
0484f9f8a6 fix(manifest): using wrong container registry for non-ha redis (#23114)
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-05-22 19:38:51 +00:00
Michael Crenshaw
d9e93f43e8 docs: add more release dates (#23113)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-22 15:22:29 -04:00
dependabot[bot]
fe52b4d6d9 chore(deps): bump docker/login-action from 3.3.0 to 3.4.0 (#23110)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-22 17:41:31 +00:00
dependabot[bot]
22c11cee10 chore(deps): bump actions/setup-node from 4.1.0 to 4.4.0 (#23108)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-22 17:41:21 +00:00
dependabot[bot]
4a41a86e43 chore(deps): bump peter-evans/create-pull-request from 7.0.5 to 7.0.8 (#23107)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-22 17:34:27 +00:00
dependabot[bot]
dbdc6eafdb chore(deps): bump sigstore/cosign-installer from 3.7.0 to 3.8.2 (#23109)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-22 13:19:17 -04:00
dependabot[bot]
5831c948db chore(deps): bump golangci/golangci-lint-action from 6.1.1 to 8.0.0 (#23111)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-22 13:14:18 -04:00
dependabot[bot]
d2d344ba01 chore(deps): bump @fortawesome/fontawesome-free from 6.5.2 to 6.7.2 in /ui (#23105)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-22 12:26:12 -04:00
dependabot[bot]
a823e12595 chore(deps): bump gitlab.com/gitlab-org/api/client-go from 0.116.0 to 0.129.0 (#23098)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-22 15:45:32 +00:00
Michael Crenshaw
878d6f715e chore(ci): fix otel dependabot group pattern (#23102)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-22 15:08:06 +00:00
dependabot[bot]
d69f37bb35 chore(deps): bump go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc from 1.35.0 to 1.36.0 (#23096)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-22 10:58:20 -04:00
sangeer
e6065b88e5 fix(updateAppsetFinalizers): Update Finalizers in addition to other metadata updates when updating Appsets (#23006)
Signed-off-by: Sangeetha Madamanchi <sangeetha@Sangeethas-MBP.attlocal.net>
Signed-off-by: raweber <99535319+raweber42@users.noreply.github.com>
Signed-off-by: Sangeetha Madamanchi <smadamanchi@expediagroup.com>
Signed-off-by: Matteo Baiguini <22518997+bygui86@users.noreply.github.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Sangeetha Madamanchi <smadamanchi@expediagroup.com>
Co-authored-by: raweber <99535319+raweber42@users.noreply.github.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
Co-authored-by: Matteo Baiguini <22518997+bygui86@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-22 10:33:50 -04:00
Michael Crenshaw
57b039f12c chore(deps): bump style-loader to v1 (#23091)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-22 10:32:58 -04:00
Michael Crenshaw
5b21f98d7c fix(server): infer resource status health for apps-in-any-ns (#22944)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-22 09:46:48 -04:00
Michael Crenshaw
198aa8a37a chore(deps): bump Dex from 2.41.1 to 2.43.0 (#23088)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-22 09:46:33 -04:00
dependabot[bot]
9183506de8 chore(deps): bump library/golang from 86b4cff to 1bcf884 in /test/remote (#23094)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-22 06:17:15 -07:00
Michael Crenshaw
9149021b2c feat(health): add crossplane and upbound health checks (#21479) (#22919)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-05-22 08:38:40 -04:00
Soumya Ghosh Dastidar
722da4e70f fix: add cooldown to prevent resetting autoheal exp backoff preemptively (#23057)
Signed-off-by: Soumya Ghosh Dastidar <gdsoumya@gmail.com>
2025-05-22 15:05:12 +05:30
dependabot[bot]
4febded784 chore(deps): bump codecov/codecov-action from 4.6.0 to 5.1.2 (#21252)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-21 21:30:20 +00:00
dependabot[bot]
f9971fa370 chore(deps): bump actions/upload-artifact from 4.4.3 to 4.5.0 (#21231)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-21 21:12:26 +00:00
dependabot[bot]
e131d273e1 chore(deps): bump prismjs from 1.27.0 to 1.30.0 in /ui (#22296)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-21 16:44:00 -04:00
dependabot[bot]
e22cd46a86 chore(deps): bump @babel/runtime from 7.14.6 to 7.26.10 in /ui (#22304)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-21 16:37:56 -04:00
dependabot[bot]
baa679d2dc chore(deps-dev): bump esbuild-loader from 2.18.0 to 4.3.0 in /ui (#21852)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-21 16:22:31 -04:00
fprovencherdrw
96039be4e0 feat(health): add Rabbitmq topology resource customizations (#22066)
Signed-off-by: Francis Provencher <fprovencher@drw.com>
2025-05-21 16:09:18 -04:00
crabique
4905876108 fix: Disable ESO refresh/push custom actions when they would do nothing (#22305)
Signed-off-by: crabique <crabique@users.noreply.github.com>
2025-05-21 15:59:24 -04:00
Matthieu MOREL
17e03ff335 chore: simplify user agent version constraint handling in interceptors (#22358)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-05-21 15:56:25 -04:00
Greg Barasch
ce4b7a28cc feat: Contour HTTPProxy health check support for issue # 22504 (#22596)
Signed-off-by: Greg Barasch <gregbarasch@gmail.com>
2025-05-21 15:54:36 -04:00
Oslan Villalobos
18a26d624b chore: Update USERS.md (#22640)
Signed-off-by: Oslan Villalobos <oslanevillalobos@gmail.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-21 19:51:15 +00:00
Rick Brouwer
d3223a8c9f feat: add Fallback condition to KEDA ScaledObject health assessment (#22844)
Signed-off-by: Rick Brouwer <rickbrouwer@gmail.com>
2025-05-21 15:23:40 -04:00
dependabot[bot]
fff55f23f1 chore(deps): bump github.com/casbin/govaluate from 1.3.0 to 1.6.0 (#23074)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-21 16:57:24 +00:00
Kanika Rana
e8f568a70d chore: use name imports for argocd Utilio (#22836)
Signed-off-by: Kanika Rana <krana@redhat.com>
2025-05-21 16:25:32 +00:00
dependabot[bot]
4210535a17 chore(deps-dev): bump @types/node from 22.15.19 to 22.15.21 in /ui-test (#23073)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-21 06:36:50 -07:00
dependabot[bot]
146a7798ed chore(deps): bump sigs.k8s.io/controller-runtime from 0.20.1 to 0.20.4 (#22959)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-20 23:03:18 -04:00
dhawos
7d58ca3ef7 chore(logs): standardize application logging (#20731) (#21442)
Signed-off-by: Louis Gérard <louis.gerard.pro@proton.me>
2025-05-20 15:48:09 -04:00
Michael Crenshaw
f4e12ad2d6 fix: revert "added tasks to upgrade Redis HA using renovate (#22054)" (#23068)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-20 19:23:26 +00:00
Peter Jiang
4f35f7f09a chore: bump gitops-engine ssd fix (#23066)
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
2025-05-20 19:14:49 +00:00
Michael Crenshaw
be6ba0e446 chore(refactor): replace trivial functions w/ standard lib (#23063)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-20 15:57:57 +00:00
Michael Crenshaw
45a8c68f2a fix(controller): only update lastTransitionTime when needed (#23018)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-20 11:26:07 -04:00
dependabot[bot]
e1db296752 chore(deps-dev): bump mocha from 11.3.0 to 11.4.0 in /ui-test (#23054)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-20 07:54:20 -07:00
dependabot[bot]
30ede8ac81 chore(deps): bump github.com/olekukonko/tablewriter from 0.0.6-0.20230925090304-df64c4bbad77 to 1.0.6 (#23030)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-20 14:37:47 +00:00
Afzal Ansari
aefa93ff4e fix: added tasks to upgrade Redis HA using renovate (#22054)
Signed-off-by: Afzal Ansari <afzal442@gmail.com>
2025-05-20 10:18:03 -04:00
Anand Francis Joseph
3e7625a255 fix(webhook): Fix panic when web URL string is empty in webhook payload (#23042)
Signed-off-by: anandf <anjoseph@redhat.com>
2025-05-20 09:47:14 -04:00
Alexei Fedotov
95efc16cd8 fix: add shellcheck and fix a few warnings (#22569)
Signed-off-by: Alexei Fedotov <alexei.fedotov@gmail.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-19 21:06:45 +00:00
Cyril Gaudin
ff7870d27c docs: fix jsonpath in 2.14-3.0 upgrade doc (#23045)
Signed-off-by: Cyril Gaudin <cyril.gaudin@camunda.com>
2025-05-19 09:56:10 -07:00
Dmitry Shmelev
25dc9605eb fix(applicationset_controller): requeue by ApplicationStatus changes (#23043)
Signed-off-by: Dmitry Shmelev <Dmitry.Shmelev@jetbrains.com>
Signed-off-by: Dmitry Shmelev <avikez@gmail.com>
Co-authored-by: rumstead <37445536+rumstead@users.noreply.github.com>
2025-05-19 09:01:24 -07:00
Sai pavan
a0a82a1407 chore: Disable trace exports to Telemetry for helm-registry server (#23020)
Signed-off-by: Sai Pavan Nunna <saipavan9999@yahoo.com>
Signed-off-by: Sai Pavan <saipavan9999@yahoo.com>
2025-05-19 11:00:48 -04:00
Nitish Kumar
309acd161c chore: replace heptio-images with argocd-e2e-container (#23040)
Signed-off-by: nitishfy <justnitish06@gmail.com>
Signed-off-by: Nitish Kumar <justnitish06@gmail.com>
2025-05-19 07:49:11 -07:00
Masanori Tani
f550dc0592 docs: Fix typo in releasing.md (#23027)
Signed-off-by: Masanori Tani <uta8a@uta8a.org>
2025-05-19 06:23:36 -07:00
Ville Vesilehto
90408cbafd chore: upgrade Go from 1.24.1 to 1.24.3 (#23026)
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
2025-05-19 12:53:38 +02:00
Jonas Mai
899e9964e0 docs: remove projects as an allowed resource type from project level policy declarations documentation (#23036)
Signed-off-by: Jonas Mai <hubwoop@users.noreply.github.com>
2025-05-19 12:38:12 +02:00
dependabot[bot]
cbb76a587a chore(deps-dev): bump mocha from 11.2.2 to 11.3.0 in /ui-test (#23031)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-19 06:25:12 -04:00
dependabot[bot]
17d356fe38 chore(deps-dev): bump @types/node from 22.15.18 to 22.15.19 in /ui-test (#23032)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-19 06:24:41 -04:00
Regina Voloshin
ec9b43f9fa feat: implement custom resource action skip-current-step for argo rollouts (#23025)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
2025-05-18 22:26:53 +03:00
siddharth
f763b2a97c feat: add pause action for argo-rollouts #20505 (#20506)
Signed-off-by: Siddharth Yadav <siddharth.yadav@king.com>
Signed-off-by: siddharth <sedflix@gmail.com>
Co-authored-by: Siddharth Yadav <siddharth.yadav@king.com>
Co-authored-by: Nitish Kumar <justnitish06@gmail.com>
2025-05-18 15:20:15 +03:00
Takumi Sue
0707bff1c2 fix: remove default spec.preserveUnknownFields ignoreDifference for CRD (#22948)
Signed-off-by: mikutas <23391543+mikutas@users.noreply.github.com>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-05-18 09:33:59 +03:00
Michael Crenshaw
797f1d693b chore(test): upgrade to mockery v3 (#22999)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-16 16:38:51 -04:00
Michael Crenshaw
6c1cfedd14 chore(deps): bump controller-gen to v0.18.0 (#23000)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-16 09:33:48 -07:00
Matteo Baiguini
6aa5f84631 docs: Added Swissblock Technologies to USERS.md (#23010)
Signed-off-by: Matteo Baiguini <22518997+bygui86@users.noreply.github.com>
2025-05-15 23:38:43 -10:00
raweber
bf488ccc4d docs: Add RequeueAfterSeconds documentation for git generator (#22890)
Signed-off-by: raweber <99535319+raweber42@users.noreply.github.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
2025-05-15 22:58:43 +02:00
Michael Crenshaw
f0d783b1e7 chore(test): fix mockery deprecation warnings (#22998)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-15 11:06:03 -07:00
dependabot[bot]
af3a37b053 chore(deps): bump github.com/Azure/kubelogin from 0.2.7 to 0.2.8 (#22813)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-15 15:31:51 +00:00
dependabot[bot]
41e7b26d03 chore(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azidentity from 1.9.0 to 1.10.0 (#22990)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-15 10:46:21 -04:00
Bo Xuan
2e4d8e58d3 refactor: Improve checkResourceStatus readability (#21260)
Signed-off-by: Boxuan Tang <tangboxuan@google.com>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-05-15 14:20:44 +00:00
Karsten Thoms
0e800341bb docs: detailed valid states for pullRequestState (#21873)
Signed-off-by: Karsten Thoms <karsten.thoms@gmail.com>
Co-authored-by: Dan Garfield <dan@codefresh.io>
2025-05-15 09:39:16 -04:00
Michael Crenshaw
8398380d46 chore(refactor): initialize slice to exact length (#22981)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-15 06:26:34 -07:00
dependabot[bot]
32eaea7533 chore(deps): bump github.com/expr-lang/expr from 1.17.2 to 1.17.3 (#22989)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-15 06:03:32 -04:00
dependabot[bot]
570b3424b0 chore(deps): bump google.golang.org/grpc from 1.72.0 to 1.72.1 (#22988)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-15 06:02:44 -04:00
dependabot[bot]
2078f40a6f chore(deps): bump chromedriver from 136.0.0 to 136.0.2 in /ui-test (#22987)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-15 06:01:54 -04:00
dependabot[bot]
7b09aef22a chore(deps-dev): bump @types/node from 22.15.17 to 22.15.18 in /ui-test (#22986)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-15 06:01:06 -04:00
dependabot[bot]
b63bf8f1d4 chore(deps): bump library/golang from 39d9e7d to 86b4cff in /test/remote (#22985)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-15 06:00:25 -04:00
Oleksandr Saulyak
be3efbd98f fix: settings request doesn't return default tracking method (#22965)
Signed-off-by: oleksandr-codefresh <oleksandr.saulyak@octopus.com>
Co-authored-by: Regina Voloshin <regina.voloshin@codefresh.io>
2025-05-15 11:26:47 +03:00
Nitish Kumar
dd5a8780e1 feat: add ability to exclude files when using git file generator (#22734)
Signed-off-by: nitishfy <justnitish06@gmail.com>
2025-05-15 03:55:27 +00:00
Atif Ali
9675487a16 feat(ui): integrate Progressive Sync feature (#22781)
Signed-off-by: Atif Ali <atali@redhat.com>
2025-05-14 16:26:42 -04:00
Michael Crenshaw
db6ece9b9f fix(test): broken e2e test (#22975)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-14 13:31:53 -04:00
rumstead
02185d7056 docs(server): no resource health when using the list api (#22954)
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
2025-05-14 11:39:44 -04:00
Michael Crenshaw
97a38b486b chore(server): remove dead code (#22955)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-13 20:45:06 -04:00
Michael Crenshaw
76a63a1cac feat(api): protect static assets endpoint from symlink traversal (#22936)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-13 16:43:14 -04:00
Grischa Ekart
44294a5102 docs: Fixed link to argocd-cm.yaml [minor] (#22923)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Signed-off-by: Grischa Ekart <gekart@gmx.de>
Signed-off-by: Dan Garfield <dan@codefresh.io>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Dan Garfield <dan@codefresh.io>
2025-05-13 14:58:02 +00:00
Nitish Kumar
e0b278fd5d docs: mention about requirement for go template when using template patch (#22950)
Signed-off-by: nitishfy <justnitish06@gmail.com>
Signed-off-by: Nitish Kumar <justnitish06@gmail.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
2025-05-13 00:58:42 -10:00
Grischa Ekart
0c20652c9a docs: Correct project role RBAC wording in projects.md [Minor] (#22922)
Signed-off-by: Grischa Ekart <gekart@users.noreply.github.com>
2025-05-12 12:17:36 +03:00
Xiaopeng Han
299286dea1 fix: app tree parentRef response missing version info (#22927)
Signed-off-by: xiaopeng <hanxiaop8@outlook.com>
2025-05-12 14:30:22 +05:30
Ibrahim Lawal
31e8ff8759 docs(users): Update USERS.md - adding Paystack (#22925)
Signed-off-by: Ibrahim Lawal <ibrahim@paystack.com>
2025-05-11 20:03:33 +02:00
Michael Crenshaw
610523b784 fix(commit-server): apply image override (#22916)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-09 19:33:24 -04:00
Michael Crenshaw
e28f6090d1 fix(commit-server): remove unnecessary init container (#22915)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-09 16:30:55 -04:00
afarbos
5a3a104793 feat: Implement grafana-operator Dashboard and Folder CRD health checks (#22493)
Signed-off-by: Arnaud Farbos <afarbos@nvidia.com>
2025-05-09 12:05:19 -07:00
dependabot[bot]
59b9ffa094 chore(deps): bump oras.land/oras-go/v2 from 2.5.0 to 2.6.0 (#22912)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-09 07:03:58 -07:00
dependabot[bot]
09f874da24 chore(deps-dev): bump @types/node from 22.15.16 to 22.15.17 in /ui-test (#22911)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-09 07:38:32 -04:00
Suraj yadav
f4e2c6ea3b fix(ui): replace current spinning webfont icon with svg icons (#21012)
Signed-off-by: Surajyadav <harrypotter1108@gmail.com>
Signed-off-by: Suraj yadav <harrypotter1108@gmail.com>
2025-05-08 20:14:31 -04:00
Linghao Su
30742f6d5d feat(ui): disable select not running pod and bring back arrow to selected pod (#21576)
Signed-off-by: linghaoSu <linghao.su@daocloud.io>
2025-05-08 16:49:06 -07:00
KoB
274e918fc8 fix(appcontroller): if a history limit is negative, automatically converted to 0 (#22036)
Signed-off-by: kingbj0429 <kingbj0429@lunit.io>
2025-05-08 16:45:08 -07:00
vivian-xu
2dafcba595 feat(ui): add keydown event to the pod dropdown menu (#20996)
Signed-off-by: vivian.zhang <vivian.zhang@daocloud.io>
2025-05-08 16:24:04 -07:00
lxw
d284b15400 feat: support gitea PR labels filter in appset PR generator (#21115) (#21148)
Signed-off-by: livelxw <livelxw@live.cn>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-05-08 22:57:40 +00:00
vamsikrishna9640
3d73f37738 docs: add missing URL configuration for Google Groups SSO with Dex (#22197)
Signed-off-by: vamsikrishna9640 <91549516+vamsikrishna9640@users.noreply.github.com>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-05-08 22:46:58 +00:00
Timothy Griffiths
bd30eea239 fix(haproxy): setting maxconn in haproxy config (#15319) (#18283)
Signed-off-by: Timothy Griffiths <griffiths.timothy@gmail.com>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-05-08 21:40:40 +00:00
raweber
56c556e707 fix: clarify applicationSet sync-policy (#22888)
Signed-off-by: raweber <99535319+raweber42@users.noreply.github.com>
2025-05-08 22:00:23 +02:00
Kylash M R
0455e840b7 docs(users): Update USERS.md - adding Schneider Electric (#22907)
Signed-off-by: Kylash M R <105107963+kylash-mr@users.noreply.github.com>
2025-05-08 09:59:49 -07:00
Michael Crenshaw
e9483a6a0d fix(health): handle nil lastTransitionTime (#22897) (#22900)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-08 07:00:30 -07:00
Mathieu Agar
992ee25bd3 fix: Race condition in nativeGitClient.LsFiles (issue #21754) (#22878)
Signed-off-by: Mathieu Agar <magar@mirakl.com>
Co-authored-by: rumstead <37445536+rumstead@users.noreply.github.com>
2025-05-08 06:29:19 -07:00
dependabot[bot]
d0afa89a82 chore(deps): bump github.com/google/go-jsonnet from 0.21.0-rc2 to 0.21.0 (#22902)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-08 15:26:39 +03:00
dependabot[bot]
bdcc705956 chore(deps): bump dario.cat/mergo from 1.0.1 to 1.0.2 (#22903)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-08 15:21:30 +03:00
dependabot[bot]
ff1b935905 chore(deps-dev): bump @types/node from 22.15.14 to 22.15.16 in /ui-test (#22904)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-08 06:26:32 -04:00
dependabot[bot]
ef07bbdea1 chore(deps): bump library/golang from 1.24.2 to 1.24.3 in /test/remote (#22905)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-08 06:26:03 -04:00
Ratul Basak
111da3966e feat(actions): parametrized actions to scale workloads (#15505) (#20097)
Signed-off-by: Ratul Basak <ratulbasak93@gmail.com>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-05-08 11:19:04 +03:00
Paul Larsen
6625d07859 chore(repo-server): unify semver resolution in new versions subpackage (#20216)
Signed-off-by: Paul Larsen <pnvlarsen@gmail.com>
Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-05-08 07:10:28 +00:00
Suraj yadav
3f3ac06fd1 feat(ui): add toggle for fullname of resources in application-details-tree (#20812)
Signed-off-by: Surajyadav <harrypotter1108@gmail.com>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-05-08 00:00:26 +00:00
Suraj yadav
bb37b10517 feat(ui): allow to sort by age in Pod-view (#20783)
Signed-off-by: Surajyadav <harrypotter1108@gmail.com>
2025-05-07 16:52:37 -07:00
Linghao Su
ceec669b0b feat(ui): support delete all expired token in project roles (#21782)
Signed-off-by: linghaoSu <linghao.su@daocloud.io>
2025-05-07 16:50:51 -07:00
Diasker
d4a20e4136 fix: prevent rootpath duplication in OIDC redirect URLs, fixes #21857 #20790 #12195 (#22254)
Signed-off-by: Diasker <kennardniko@foxmail.com>
2025-05-07 16:43:23 -07:00
Shun Nishitsuji
c7fa14e3b8 fix(repo-server): When using custom kustomize versions, obtain the correct path (#21449) (#21537)
Signed-off-by: asuforce <owata.sn@gmail.com>
2025-05-07 16:40:05 -07:00
Geoffrey MUSELLI
6047e91d15 feat(AppProject): Add sync window description (#20766)
Signed-off-by: gmuselli <geoffrey.muselli@gmail.com>
Signed-off-by: speedfl <geoffrey.muselli@gmail.com>
Signed-off-by: gmuselli <Geoffrey Muselli>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: gmuselli <Geoffrey Muselli>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-05-07 23:15:38 +00:00
Marc Khair
e578b85410 feat(health): add kyverno Policy resource customization (#21552)
Signed-off-by: Marc Khair <67377306+marckhair@users.noreply.github.com>
2025-05-07 16:14:34 -07:00
dependabot[bot]
92589dea2f chore(deps): bump library/busybox from sha256:498a000f370d8c37927118ed80afe8adc38d1edcbfc071627d17b25c88efcab0 to sha256:37f7b378a29ceb4c551b1b5582e27747b855bbfaa73fa11914fe0df028dc581f in /test/e2e/multiarch-container (#22703)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-07 18:17:16 -04:00
Suraj yadav
38e7a03c51 fix(ui): Added tooltip for buttons in narrow window (#20886)
Signed-off-by: Surajyadav <harrypotter1108@gmail.com>
2025-05-07 14:51:32 -07:00
asela-nomihealth
0b7d7df6ac docs: update USERS.md to include Artemis Health (#22895)
Signed-off-by: asela-nomihealth <120056260+asela-nomihealth@users.noreply.github.com>
Co-authored-by: asela-nomihealth <arigsela@gmail.com>
2025-05-07 17:06:37 -04:00
dependabot[bot]
a12f517ebd chore(deps-dev): bump @types/node from 22.15.11 to 22.15.14 in /ui-test (#22886)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-07 06:09:30 -07:00
dependabot[bot]
f31807d5da chore(deps): bump library/golang from d9db321 to 8131d99 in /test/remote (#22818)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Dan Garfield <dan@codefresh.io>
2025-05-07 06:09:10 -07:00
jheyduk
acd8844064 fix(docs): upgrading 3.0 docs (#22891)
Signed-off-by: Joerg Heyduk <joerg@heyduk.org>
2025-05-07 12:17:03 +02:00
Oliver Gondža
73f68af2a6 fix(docs): Fix UI port in E2E docs (#22881)
Signed-off-by: Oliver Gondža <ogondza@gmail.com>
2025-05-07 10:28:44 +02:00
Dmitry Fedorov
70fc269834 chore(docs): fix indentation for Important admonition (#22883)
Signed-off-by: Dmitry Fedorov <fedorovdima@users.noreply.github.com>
2025-05-06 18:30:45 -04:00
dependabot[bot]
73c976003a chore(deps): bump golang.org/x/net from 0.39.0 to 0.40.0 (#22874)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-06 15:09:54 +00:00
renovate[bot]
362dc663cd chore(deps): update dependency gotestyourself/gotestsum to v1.12.2 (#22875)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-06 07:18:13 -07:00
dependabot[bot]
410a0a54cf chore(deps): bump golang.org/x/term from 0.31.0 to 0.32.0 (#22873)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-06 07:17:25 -07:00
dependabot[bot]
c37be2122b chore(deps): bump golang.org/x/oauth2 from 0.29.0 to 0.30.0 (#22871)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-06 07:16:37 -07:00
dependabot[bot]
969b043503 chore(deps-dev): bump @types/node from 22.15.3 to 22.15.11 in /ui-test (#22870)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-06 07:16:16 -07:00
almoelda
0dfdb0a86a fix(cli): Prevent Get & Sync from Hanging on Invalid Application Spec (#21702)
Signed-off-by: almoelda <42950693+almoelda@users.noreply.github.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-05-06 00:54:56 +00:00
Nitish Kumar
6cf29619ae feat(cli): Add Plugin Support to the Argo CD CLI (#20074)
Signed-off-by: nitishfy <justnitish06@gmail.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-05-05 16:12:33 -07:00
dependabot[bot]
9a738b2880 chore(deps): bump github.com/ktrysmt/go-bitbucket from 0.9.83 to 0.9.85 (#22866)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-05 10:50:46 -07:00
dependabot[bot]
f6861aa353 chore(deps): bump github.com/grpc-ecosystem/go-grpc-middleware/v2 from 2.3.1 to 2.3.2 (#22868)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-05 06:16:29 -04:00
dependabot[bot]
11736abfb9 chore(deps): bump selenium-webdriver from 4.31.0 to 4.32.0 in /ui-test (#22867)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-05 06:16:07 -04:00
renovate[bot]
8950d0a46c chore(deps): update module github.com/golangci/golangci-lint to v2.1.6 (#22865)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 06:12:24 -04:00
Hrittik Roy
5cd1ef9e67 docs: add external IP LoadBalancer Step (#22851)
Signed-off-by: Hrittik Roy <67012359+hrittikhere@users.noreply.github.com>
2025-05-02 18:29:44 -04:00
dependabot[bot]
53a2005b43 chore(deps-dev): bump mocha from 11.0.1 to 11.2.2 in /ui-test (#22849)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-02 08:11:24 -07:00
CMDMichalKoval
99faf82474 feat(appset): add target branch support for bitbucket cloud pull request generator (#22402)
Signed-off-by: Michal Koval <michal.koval@commander.sk>
Co-authored-by: Ishita Sequeira <46771830+ishitasequeira@users.noreply.github.com>
2025-05-02 08:54:24 -04:00
dependabot[bot]
7d81d1a59e chore(deps): bump library/redis from d000041 to 7df1eef in /test/container (#22841)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-01 08:59:22 -07:00
dependabot[bot]
9d93eb2054 chore(deps): bump library/golang from 8131d99 to 30baaea in /test/container (#22840)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-01 06:09:34 -07:00
dependabot[bot]
08d52f3617 chore(deps): bump chromedriver from 135.0.4 to 136.0.0 in /ui-test (#22839)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-01 06:09:14 -07:00
Dmitry Fedorov
d0dbafcf0d chore(docs): fix ZipRecruiter name in USERS.md (#22837)
Signed-off-by: Dmitry Fedorov <fedorovdima@users.noreply.github.com>
2025-04-30 17:35:36 -06:00
dependabot[bot]
274bdcca8b chore(deps): bump library/golang from d9db321 to 8131d99 in /test/container (#22820)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Dan Garfield <dan@codefresh.io>
2025-04-30 09:20:29 -07:00
dependabot[bot]
8d8ca44487 chore(deps): bump library/redis from 8bc6664 to d000041 in /test/container (#22821)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Dan Garfield <dan@codefresh.io>
2025-04-30 09:20:04 -07:00
Afzal Ansari
ba9ad75ac7 docs: remove argocd installation redundant steps for Mac users (#22705)
Signed-off-by: Afzal Ansari <afzal442@gmail.com>
2025-04-29 15:37:54 -06:00
Revital Barletz
aa7f5726e8 docs: Helm values can't be used as soon as valuesObject is used (#22807)
Signed-off-by: Revital Barletz <revitalbarletz@gmail.com>
2025-04-29 15:35:22 -06:00
Revital Barletz
a7dce39444 docs: Update sync-waves.md to include more details about phases and waves (#22768)
Signed-off-by: Revital Barletz <revitalbarletz@gmail.com>
Co-authored-by: Dan Garfield <dan@codefresh.io>
2025-04-28 14:55:49 -06:00
Peter Jiang
db9c82a886 fix: remove project from cache key for project scoped credentials (#22712)
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
2025-04-28 13:26:39 -04:00
dependabot[bot]
a00446565c chore(deps-dev): bump @types/node from 22.15.0 to 22.15.2 in /ui-test (#22812)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-28 06:14:25 -07:00
renovate[bot]
1cd3ac511c chore(deps): update dependency pymdown-extensions to v10.15 (#22811)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 05:12:10 -07:00
dependabot[bot]
a5626a3432 chore(deps): bump library/golang from 1ecc479 to d9db321 in /test/remote (#22790)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-28 04:58:28 -07:00
Jorge Ivan Tapicha Bedoya
a9dff073b2 chore(docs): Added Yuno to the USERS.md (#22806)
Signed-off-by: Jorge Ivan Tapicha Bedoya <jitapichab@gmail.com>
2025-04-27 21:43:01 -04:00
Yiwei Gong
814a24e229 fix(ui): resolve refresh page issue with multi system extensions (#22775)
Signed-off-by: Yiwei Gong <imwithye@gmail.com>
Co-authored-by: Ishita Sequeira <46771830+ishitasequeira@users.noreply.github.com>
2025-04-27 20:18:36 -04:00
Mike Bryant
b2ad0122d5 fix: Only port-forward to ready pods (#10610) (#22794)
Signed-off-by: Mike Bryant <mike.bryant@mettle.co.uk>
2025-04-27 18:18:02 -04:00
dependabot[bot]
89f006a351 chore(deps): bump library/redis from 7.4.2 to 7.4.3 in /test/container (#22789)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-27 18:17:04 -04:00
dependabot[bot]
7079a4cc7a chore(deps-dev): bump @types/node from 22.14.1 to 22.15.0 in /ui-test (#22788)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-27 18:16:39 -04:00
dependabot[bot]
5500a375f7 chore(deps): bump chromedriver from 135.0.3 to 135.0.4 in /ui-test (#22787)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-27 18:16:08 -04:00
geichelberger
19669d2daf feat: add repository_id to AppSet generators (#15820) (#22416)
Signed-off-by: Gregor Eichelberger <gregor.eichelberger@tuwien.ac.at>
2025-04-27 17:39:26 -04:00
Mike Tougeron
895dcf7fa7 fix: Allow ClusterAPI MachinePool scaling to be considered Healthy (#22040)
Signed-off-by: Mike Tougeron <tougeron@adobe.com>
2025-04-27 16:55:41 -04:00
dependabot[bot]
ca431dc5e4 chore(deps): bump google.golang.org/grpc from 1.71.1 to 1.72.0 (#22742)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-27 16:48:09 -04:00
renovate[bot]
eaf83ba29d chore(deps): update module github.com/golangci/golangci-lint to v2.1.5 (#22783)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-25 08:34:37 -07:00
Linghao Su
fdb035017f fix(ui): fix bearerToken validate in helm connect page (#22791)
Signed-off-by: linghaoSu <linghao.su@daocloud.io>
2025-04-25 08:33:22 -07:00
dependabot[bot]
0ad3a2c986 chore(deps): bump chromedriver from 135.0.2 to 135.0.3 in /ui-test (#22774)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-24 07:26:41 -07:00
Fernando Crespo Grávalos
f26b7cd1ac fix(ApplicationSet): Check strategy type to verify it's a progressive sync (#22563)
Signed-off-by: Fernando Crespo Gravalos <fcrespo@fastly.com>
Signed-off-by: Fernando Crespo Grávalos <59588094+fcrespofastly@users.noreply.github.com>
Co-authored-by: rumstead <37445536+rumstead@users.noreply.github.com>
2025-04-23 11:30:00 -07:00
dependabot[bot]
0be041a834 chore(deps): bump github.com/aws/aws-sdk-go from 1.55.6 to 1.55.7 (#22761)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-23 09:11:02 -07:00
dependabot[bot]
3a529f338d chore(deps): bump github.com/ktrysmt/go-bitbucket from 0.9.82 to 0.9.83 (#22762)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-23 09:10:38 -07:00
Revital Barletz
4aea93b867 docs: Update Appset-Any-Namespace.md - removed extra 'and' for clarity (#22767)
Signed-off-by: Revital Barletz <revitalbarletz@gmail.com>
2025-04-23 02:04:34 -10:00
Revital Barletz
0864318ac2 docs: multiple resources should set a relative path in the valueFiles (#22745)
Signed-off-by: Revital Barletz <revitalbarletz@gmail.com>
Signed-off-by: Dan Garfield <dan@codefresh.io>
Co-authored-by: Dan Garfield <dan@codefresh.io>
2025-04-22 16:54:17 +00:00
Oliver Gondža
27ae11ac58 docs: Style and formatting fixes in the developer guide (#22677)
Signed-off-by: Oliver Gondža <ogondza@gmail.com>
2025-04-22 07:45:42 -07:00
dependabot[bot]
c8c74b5d83 chore(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azidentity from 1.8.2 to 1.9.0 (#22614)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-21 22:06:13 -04:00
Regina Voloshin
d22e28a28e fix: AppSet PullRequest and SCM generators get 401 from GitHub without tokenRef (#22737)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
2025-04-21 15:38:16 -04:00
dependabot[bot]
713f9473af chore(deps): bump github.com/casbin/casbin/v2 from 2.104.0 to 2.105.0 (#22732)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-21 06:17:47 -07:00
dependabot[bot]
04809649f8 chore(deps): bump library/golang from 1.24.2@sha256:1ecc479bc712a6bdb56df3e346e33edcc141f469f82840bab9f4bc2bc41bf91d to sha256:d9db32125db0c3a680cfb7a1afcaefb89c898a075ec148fdc2f0f646cc2ed509 in /test/container (#22729)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-21 06:17:25 -07:00
Blake Pettersson
8c3c778bee fix: do not normalize resource tracking on live crds (#22722)
Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
2025-04-21 14:48:45 +05:30
Pasha Kostohrys
2bd2488989 feat: Enable SkipDryRunOnMissingResource sync option on Application level (#22679)
Co-authored-by: pasha <pasha.k@fyxt.com>
2025-04-20 14:54:38 +03:00
dependabot[bot]
86fa92d954 chore(deps): bump library/ubuntu from 24.04@sha256:80dd3c3b9c6cecb9f1667e9290b3bc61b78c2678c02cbdae5f0fea92cc6734ab to sha256:1e622c5f073b4f6bfad6632f2616c7f59ef256e96fe78bf6a595d1dc4376ac02 in /test/container (#22716)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-20 14:42:21 +03:00
Denis Karpelevich
569f5d4ce5 docs: Document GitHub App credentials GitHub Enterprise Base URL when creating repository (argoproj#22389) (#22433)
Signed-off-by: Denis Karpelevich <dkarpele@redhat.com>
2025-04-20 13:33:27 +03:00
Sascha Spreitzer
4b6566a8ef docs: add a precise description on helm chart prerelease version comparison. Fixes #21818 (#22724)
Signed-off-by: Sascha Spreitzer <sascha@spreitzer.ch>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-04-19 20:33:43 +02:00
Michael Crenshaw
bde7bcfb29 fix(ui): avoid spurious error on hydration (#22506) (#22711)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-04-17 16:34:34 -07:00
Grant Birkinbine
5002f8a24e fix: disable golang caching on releases to harden against cache poisoning (#22699)
Signed-off-by: Grant Birkinbine <grant.birkinbine@gmail.com>
2025-04-17 08:16:15 -07:00
dependabot[bot]
23f6822cab chore(deps): bump chromedriver from 135.0.1 to 135.0.2 in /ui-test (#22704)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-17 06:20:38 -07:00
dependabot[bot]
b85fec60a5 chore(deps): bump library/redis from 7.4.2@sha256:ca65ea36ae16e709b0f1c7534bc7e5b5ac2e5bb3c97236e4fec00e3625eb678d to sha256:fbdbaea47b9ae4ecc2082ecdb4e1cea81e32176ffb1dcf643d422ad07427e5d9 in /test/container (#22702)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-17 06:20:10 -07:00
kahou82
8fd61195f0 fix: Race condition occurs during initial sharing (#22696)
Signed-off-by: Kahou Lei <kahou82@gmail.com>
Co-authored-by: Ishita Sequeira <46771830+ishitasequeira@users.noreply.github.com>
2025-04-17 02:03:14 +00:00
dependabot[bot]
89d1ff95cf chore(deps): bump http-proxy-middleware from 2.0.7 to 2.0.9 in /ui (#22698)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-16 21:16:14 -04:00
Michael Crenshaw
2d2efdc48f chore(deps): bump github.com/argoproj/pkg to v2.0.1 (#22516)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-04-16 13:15:42 -07:00
Nitish Kumar
a5b57d43a2 test: add unit tests for argocd admin export command to validate behaviour (#22391)
Signed-off-by: nitishfy <justnitish06@gmail.com>
2025-04-16 21:33:30 +05:30
Michael Crenshaw
e97114c3cd docs: remove links to code (#22680)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-04-16 07:13:57 -07:00
dependabot[bot]
6ce6976cf1 chore(deps): bump github.com/go-git/go-git/v5 from 5.14.0 to 5.16.0 (#22684)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-16 07:13:40 -07:00
dependabot[bot]
8c2fc74306 chore(deps): bump github.com/bradleyfalzon/ghinstallation/v2 from 2.14.0 to 2.15.0 (#22685)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-16 07:13:20 -07:00
sivchari
8e846a56f9 fix: test/container/Dockerfile (#22681)
Signed-off-by: sivchari <shibuuuu5@gmail.com>
2025-04-15 11:14:52 -07:00
renovate[bot]
88ecbe2e27 chore(deps): update module github.com/golangci/golangci-lint to v2.1.2 (#22675)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 09:47:54 -07:00
Michael Crenshaw
a2233562df fix(controller): always set health.status.lastTransitionTime (#22665) (#22666)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-04-14 17:16:40 +00:00
Nitish Kumar
e72ebb0098 fix: respect delete confirmation for argocd app deletion (#22657)
Signed-off-by: nitishfy <justnitish06@gmail.com>
2025-04-14 07:49:28 -07:00
dependabot[bot]
f6e15d2984 chore(deps): bump sigs.k8s.io/structured-merge-diff/v4 from 4.6.0 to 4.7.0 (#22653)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-14 04:55:30 -07:00
dependabot[bot]
600ab18087 chore(deps-dev): bump @types/node from 22.14.0 to 22.14.1 in /ui-test (#22652) 2025-04-14 07:19:33 -04:00
dependabot[bot]
5e1d2b9bb7 chore(deps): bump github.com/prometheus/client_model from 0.6.1 to 0.6.2 (#22654) 2025-04-14 07:19:03 -04:00
renovate[bot]
faf0073ebc chore(deps): update module github.com/golangci/golangci-lint to v2.1.1 (#22458)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-12 17:47:52 -04:00
dependabot[bot]
127eef95fd chore(deps): bump github.com/prometheus/client_golang from 1.21.1 to 1.22.0 (#22615)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-12 09:13:47 +01:00
renovate[bot]
01e8bd1c2f chore(deps): update dependency markdown to v3.8 (#22642)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-12 09:11:46 +01:00
Nirmal Arya
1eeaab4564 Added Bayer AG to the USERS.md (#22645)
Signed-off-by: Nirmal Arya <2323680+nirmalarya@users.noreply.github.com>
2025-04-11 22:13:50 -06:00
dependabot[bot]
923edeafa0 chore(deps): bump library/golang from 18a1f2d to 1ecc479 in /test/remote (#22636)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-11 07:42:23 -07:00
dependabot[bot]
8cc091c3d2 chore(deps): bump library/golang from 18a1f2d to 1ecc479 in /test/container (#22637)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-11 07:42:09 -07:00
dependabot[bot]
580ae1db1f chore(deps-dev): bump dotenv from 16.4.7 to 16.5.0 in /ui-test (#22638)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-11 07:41:51 -07:00
Wesley Charles Blake
4d0d80731e docs: Adds chronicle-labs to users (#22635)
Signed-off-by: Wesley Charles Blake <hello@stratonode.dev>
2025-04-11 07:41:27 -07:00
Seth Gupton
cde5b4b7d4 fix: Increase Scan count and move Scan outside of mutex lock to avoid slow calls timing out (#17645) (#21926)
Signed-off-by: Seth Gupton <seth.gupton@mastery.net>
2025-04-10 14:08:21 -07:00
Christian Hernandez
8401dcead0 docs: Removed IgnoreExtraneous since it is now in the new compare-options doc (#22632)
Signed-off-by: Christian Hernandez <christian@chernand.io>
2025-04-10 15:40:13 +00:00
Oliver Gondža
f54238bae4 docs: Style and formatting improvements to User Guide (#22622)
Signed-off-by: Oliver Gondža <ogondza@gmail.com>
Co-authored-by: rumstead <37445536+rumstead@users.noreply.github.com>
2025-04-10 07:47:13 -07:00
dependabot[bot]
a1fd1ba178 chore(deps): bump chromedriver from 135.0.0 to 135.0.1 in /ui-test (#22628)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-10 07:03:30 -04:00
dependabot[bot]
e4d7103508 chore(deps): bump library/golang from c0b66cf to 18a1f2d in /test/remote (#22627)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-10 07:03:05 -04:00
dependabot[bot]
e292cc4441 chore(deps): bump library/golang from c0b66cf to 18a1f2d in /test/container (#22626)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-10 07:02:37 -04:00
de-slalonde
e4a8c9ee98 docs(users): Add DigitalEd to official USERS.md (#22624)
Signed-off-by: Sam Lalonde <slalonde@digitaled.com>
2025-04-09 12:47:38 -07:00
Atif Ali
999dbb264e feat(UI): add enabled field to explicitly set in automatedSync in SyncPolicy (#22482)
Signed-off-by: Atif Ali <atali@redhat.com>
2025-04-09 15:43:43 -04:00
dependabot[bot]
81dda34ab8 chore(deps): bump library/golang from 991aa6a to c0b66cf in /test/remote (#22618)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-09 06:11:19 -07:00
dependabot[bot]
4e2d2d3459 chore(deps): bump library/golang from 991aa6a to c0b66cf in /test/container (#22613)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-09 06:10:44 -07:00
Peter Jiang
99b8761a64 chore(docs): Update Server Side Diff Documentation (#22600)
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
2025-04-08 20:21:43 +00:00
dependabot[bot]
93a8014aed chore(deps): bump github.com/go-jose/go-jose/v4 from 4.0.5 to 4.1.0 (#22598)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-08 07:54:02 -07:00
dependabot[bot]
f7b5bef7db chore(deps): bump library/golang from 1.24.1 to 1.24.2 in /test/container (#22597)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-08 08:15:47 -04:00
dependabot[bot]
fc147e3e9a chore(deps): bump golang.org/x/net from 0.38.0 to 0.39.0 (#22599)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-08 09:21:46 +01:00
Alexandre Gaudreault
76d1772b5c fix: do not exclude APIService resources (#22586)
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-04-07 11:22:46 +00:00
dependabot[bot]
17337de6eb chore(deps): bump golang.org/x/oauth2 from 0.28.0 to 0.29.0 (#22580)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 11:47:57 +01:00
dependabot[bot]
a85a760ffe chore(deps): bump library/registry from 2.8 to 3.0 in /test/container (#22575)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 10:36:50 +00:00
dependabot[bot]
c5f7898382 chore(deps): bump selenium-webdriver from 4.30.0 to 4.31.0 in /ui-test (#22574)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 05:56:40 -04:00
dependabot[bot]
b99e8e73c0 chore(deps-dev): bump typescript from 5.8.2 to 5.8.3 in /ui-test (#22573)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 05:56:18 -04:00
dependabot[bot]
bc73ff9023 chore(deps): bump github.com/jarcoal/httpmock from 1.3.1 to 1.4.0 (#22576)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 05:55:43 -04:00
dependabot[bot]
54d7dbff62 chore(deps): bump github.com/fsnotify/fsnotify from 1.8.0 to 1.9.0 (#22577)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 05:55:18 -04:00
dependabot[bot]
3a49fc87eb chore(deps): bump library/golang from 1.24.1 to 1.24.2 in /test/remote (#22581)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 05:54:40 -04:00
dependabot[bot]
d016dbec4d chore(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azcore from 1.17.1 to 1.18.0 (#22564)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-05 23:39:43 +01:00
dependabot[bot]
6fb4cb56eb chore(deps): bump go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc from 1.32.0 to 1.35.0 (#22215)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 11:21:47 -07:00
dependabot[bot]
d0d53d3639 chore(deps): bump golang.org/x/net from 0.37.0 to 0.38.0 (#22509)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 10:14:44 -07:00
dependabot[bot]
fa02355001 chore(deps): bump google.golang.org/grpc from 1.71.0 to 1.71.1 (#22542)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 10:14:12 -07:00
dependabot[bot]
0e17da4880 chore(deps): bump github.com/ktrysmt/go-bitbucket from 0.9.81 to 0.9.82 (#22543)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 10:13:53 -07:00
dependabot[bot]
bc00d08261 chore(deps): bump code.gitea.io/sdk/gitea from 0.20.0 to 0.21.0 (#22565)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 10:12:04 -07:00
dependabot[bot]
bd5e6af609 chore(deps): bump github.com/coreos/go-oidc/v3 from 3.13.0 to 3.14.1 (#22566)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 10:11:47 -07:00
dependabot[bot]
7a2242a6f5 chore(deps): bump library/golang from c5adecd to 8678013 in /test/remote (#22327)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 08:11:38 -07:00
dependabot[bot]
765d2d36b6 chore(deps): bump go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc from 0.59.0 to 0.60.0 (#22214)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 08:10:43 -07:00
dependabot[bot]
2ed31a7b8c chore(deps): bump go.opentelemetry.io/otel/sdk from 1.34.0 to 1.35.0 (#22210)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 08:10:19 -07:00
dependabot[bot]
73495d0707 chore(deps): bump chromedriver from 134.0.2 to 135.0.0 in /ui-test (#22555)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-03 05:21:03 -07:00
dependabot[bot]
f63b807789 chore(deps-dev): bump @types/node from 22.13.17 to 22.14.0 in /ui-test (#22556)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-03 05:20:36 -07:00
Dag Andersen
0f7da63220 docs(users): Add Doubble to official USERS.md (#22557)
Signed-off-by: Dag Andersen <dagbjerreandersen@gmail.com>
2025-04-03 05:20:12 -07:00
xvirgov
8bfb4f456a fix: fixing broken md link (#22517)
Signed-off-by: Michal Virgovic <michal.virgovic1@gmail.com>
2025-04-02 10:53:06 -07:00
Matthieu MOREL
5b0d76503f chore: clean-up golangci-lint configuration (#22544)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-04-02 08:04:17 -07:00
Alex Eftimie
6bee96c375 fix: #20183 preserve syncOptions when rolling back from the UI (#21871)
Signed-off-by: Alex Eftimie <alex.eftimie@getyourguide.com>
Co-authored-by: Linghao Su <slh001@live.cn>
2025-04-02 09:26:20 -04:00
dependabot[bot]
38b4cba146 chore(deps-dev): bump @types/node from 22.13.14 to 22.13.17 in /ui-test (#22541)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 06:29:22 -04:00
Jagermaist3r
e55840a455 docs: Add Wakacje.pl to USERS.md (#22534)
Signed-off-by: Jagermaist3r <101060952+Jagermaist3r@users.noreply.github.com>
2025-04-01 06:22:18 -07:00
Alex Kári Ívarsson
b3cd6fee77 chore: Add Icelandair to USERS.md (#22533)
Signed-off-by: Alex Kári Ívarsson <alexkivars@gmail.com>
2025-04-01 06:21:10 -07:00
Max Gautier
c73796da90 fix: Always create manual long lived token (#19970)
Signed-off-by: Max Gautier <mg@max.gautier.name>
2025-03-31 14:29:08 +00:00
Michael Crenshaw
ffe42256e9 chore: fix missed lint issues (#22518)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-03-31 08:15:54 -04:00
Michael Crenshaw
0ec46f6857 chore(ci): upgrade golangci-lint to v2 (#22484)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-27 12:37:52 -04:00
Eadred
4a987ddbf2 fix: Check for semver constraint matching in application webhook handler (#21634) (#21648)
Signed-off-by: eadred <eadred77@googlemail.com>
2025-03-27 11:26:02 -04:00
dependabot[bot]
344b434cc5 chore(deps-dev): bump @types/node from 22.13.13 to 22.13.14 in /ui-test (#22495)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-27 06:45:58 -07:00
Javier Solana
75098e5aed chore: add "dry_run" label to sync metrics (#22010)
Co-authored-by: Javier Solana <javier.solana@cabify.com>
Co-authored-by: Pasha Kostohrys <pasha.kostohrys@gmail.com>
2025-03-26 19:31:12 -04:00
Alexy Mantha
d9ef10a817 feat(hydrator): handle sourceHydrator fields from webhook (#19397) (#22485)
Signed-off-by: daengdaengLee <gunho1020@gmail.com>
Signed-off-by: Alexy Mantha <alexy@mantha.dev>
Co-authored-by: Kunho Lee <gunho1020@gmail.com>
2025-03-26 12:08:35 -04:00
Nitish Kumar
06dd876038 docs: update apps/appsets in any namespace flags documentation (#22480)
Signed-off-by: nitishfy <justnitish06@gmail.com>
2025-03-26 07:03:33 -07:00
Anand Francis Joseph
2fbace3fe7 feat(webhook): Fixed manifest-generate-paths annotation support for monorepos in BitBucket (#21811)
Signed-off-by: anandf <anjoseph@redhat.com>
2025-03-26 08:27:06 -04:00
dependabot[bot]
a1f90b5cb6 chore(deps): bump github.com/expr-lang/expr from 1.17.1 to 1.17.2 (#22477)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-25 06:14:20 -07:00
dependabot[bot]
c943ad2d40 chore(deps): bump google.golang.org/protobuf from 1.36.5 to 1.36.6 (#22478)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-25 06:13:55 -07:00
dependabot[bot]
76f3e9841d chore(deps-dev): bump @types/node from 22.13.11 to 22.13.13 in /ui-test (#22479)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-25 06:13:17 -07:00
dependabot[bot]
f8b5b0ba54 chore(deps): bump github.com/google/go-jsonnet from 0.21.0-rc1.0.20250311032901-bc787d68ca30 to 0.21.0-rc2 (#22454)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-24 15:16:15 -04:00
Michael Crenshaw
d2da1b3f4e chore: move pkg/exec in-tree (#22175) (#22460)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-03-24 14:29:34 -04:00
Aaron Hoffman
66d7f1b060 docs: add notifications examples section (#22032)
Signed-off-by: Aaron Hoffman <31711338+Aaron-9900@users.noreply.github.com>
Co-authored-by: Pasha Kostohrys <pasha.kostohrys@gmail.com>
2025-03-24 14:27:04 -04:00
dependabot[bot]
fe8083adf5 chore(deps): bump github.com/Azure/kubelogin from 0.2.6 to 0.2.7 (#22453)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-24 12:31:24 -04:00
Anand Kumar Singh
fe347e39f7 fix: update field name from syncPolicy.automated.enable to enabled (#22440)
Signed-off-by: Anand Kumar Singh <anandrkskd@gmail.com>
2025-03-24 10:10:16 -04:00
hua-ri
d171179dbd fix: invalid version for 'k8s.io/externaljwt@v0.0.0' (#22434)
Signed-off-by: qiqiuyang <qiqiuyang@163.com>
2025-03-24 06:25:17 -07:00
dependabot[bot]
528f6ad58b chore(deps): bump selenium-webdriver from 4.29.0 to 4.30.0 in /ui-test (#22451)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-24 06:29:01 -04:00
dependabot[bot]
77ecfe527e chore(deps-dev): bump @types/node from 22.13.10 to 22.13.11 in /ui-test (#22452)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-24 06:28:46 -04:00
Alexandre Gaudreault
a628db994b chore: allow to set CGO flags in makefile (#22437)
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-03-23 22:02:18 -04:00
dependabot[bot]
881448ec76 chore(deps): bump github.com/golang-jwt/jwt/v5 from 5.2.1 to 5.2.2 (#22441)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-22 22:23:35 -04:00
dependabot[bot]
ff9e40ef8f chore(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azcore from 1.17.0 to 1.17.1 (#22429)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-22 18:46:33 -04:00
dependabot[bot]
9c177584fa chore(deps): bump github.com/golang-jwt/jwt/v4 from 4.5.1 to 4.5.2 (#22442)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-22 18:45:43 -04:00
Anand Francis Joseph
3f90f99ee8 fix(cli): Fix for removing auto generated tag for applicationset command (#22446)
Signed-off-by: anandf <anjoseph@redhat.com>
2025-03-22 13:48:15 -04:00
dependabot[bot]
a916289a66 chore(deps): bump github.com/redis/go-redis/v9 from 9.7.1 to 9.7.3 (#22425)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-21 13:33:59 -04:00
Andrii Korotkov
6d63683bff chore(deps): Update some dependencies versions (#22228) (#22260)
Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>
2025-03-21 16:27:12 +00:00
Linghao Su
401e835d08 fix(ui): use correct monaco editor config for correct behavior (#22421)
Signed-off-by: linghaoSu <linghao.su@daocloud.io>
2025-03-21 10:27:32 -04:00
Anand Kumar Singh
432a0cdef4 feat: add enable field for automatedSync (#21999)
Signed-off-by: Anand Kumar Singh <anandrkskd@gmail.com>
2025-03-21 07:47:01 -04:00
nmirasch
b4fc122d3b fix: CVE-2025-26791 upgrading redoc dep to 2.4.0 to avoid DOMPurify b… (#21998)
Signed-off-by: nmirasch <neus.miras@gmail.com>
2025-03-21 07:31:02 -04:00
Amit Oren
98faf392a7 docs: Add note about needing to restart the controller when excluding child resources (#22362)
Signed-off-by: Amit Oren <amit@coralogix.com>
Signed-off-by: Amit Oren <github@amitoren.dev>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Nitish Kumar <justnitish06@gmail.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-03-20 20:58:02 +00:00
ianyc
6340e7ebdd fix: UI log viewer 'Show logs since a given time' filed has no effect bug #22330 (#22331)
Signed-off-by: ianyc <ychsiaoo@gmail.com>
2025-03-20 16:46:33 -04:00
Linghao Su
04186aa3e4 fix(ui): fix podGroup expansion background (#22279)
Signed-off-by: linghaoSu <linghao.su@daocloud.io>
2025-03-20 15:08:51 -04:00
almoelda
6d7e75d5cc feat: Add link to get the list of applications of a cluster/project (#21561)
Signed-off-by: Almo Elda <almogldbh@gmail.com>
2025-03-20 13:17:02 -04:00
dependabot[bot]
545b26756d chore(deps): bump github.com/Azure/kubelogin from 0.2.3 to 0.2.6 (#22419)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-20 10:27:24 -04:00
Ishita Sequeira
39e483ddef chore: add ApplicationSet Controller docs to clisdocsgen (#22417)
Signed-off-by: Ishita Sequeira <ishiseq29@gmail.com>
2025-03-20 15:54:58 +02:00
dependabot[bot]
9f37d43672 chore(deps): bump github.com/Azure/kubelogin from 0.1.9 to 0.2.3 (#22401)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 10:31:37 -04:00
dependabot[bot]
08f34b4545 chore(deps): bump github.com/expr-lang/expr from 1.17.0 to 1.17.1 (#22400)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 10:30:42 -04:00
Alexandre Gaudreault
8a4ba4d2e2 ci: add breaking changes section to changelog (#22395)
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-03-18 13:17:16 -04:00
Atif Ali
f6f10c0521 fix: handle annotated git tags correctly in repo server cache (#21771)
Signed-off-by: Atif Ali <atali@redhat.com>
2025-03-18 11:46:19 -04:00
github-actions[bot]
dd0c300698 [Bot] docs: Update Snyk report (#22360)
Signed-off-by: CI <ci@argoproj.com>
Co-authored-by: CI <ci@argoproj.com>
2025-03-18 11:10:53 -04:00
dependabot[bot]
065e298ab4 chore(deps): bump github.com/expr-lang/expr from 1.16.9 to 1.17.0 (#22364)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-18 08:05:51 -07:00
renovate[bot]
2a50dcb6c2 chore(deps): update module github.com/golangci/golangci-lint to v1.64.8 (#22384)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-18 09:58:05 -04:00
dependabot[bot]
a2e99a055a chore(deps): bump github.com/casbin/casbin/v2 from 2.103.0 to 2.104.0 (#22388)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-18 09:57:26 -04:00
Michael Crenshaw
a445fcb4f6 chore(ci): address goreleaser deprecations (#22379)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-03-18 09:50:16 -04:00
github-actions[bot]
20b1870d75 chore: Bump version in master (#22383)
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>
2025-03-17 21:29:53 +00:00
Andrii Korotkov
b0d00d521a fix: Enable service account token automount for haproxy (#22226) (#22353)
Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>
2025-03-17 20:34:53 +00:00
Michael Crenshaw
bde63b5a5b chore(ci): improve previous-version script readability, fix bug (#22378)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-03-17 15:17:50 -04:00
Andrii Korotkov
1a25d7c52c fix: Account for batch event processing in e2e tests (#22356)
Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>
2025-03-17 14:59:40 -04:00
Michael Crenshaw
e9ae886c3c fix(ci): get correct previous version, fail workflow if not (#22376)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-03-17 13:58:17 -04:00
Michael Crenshaw
9a8ec4aa09 fix(ci): use tags instead of branches (#22372)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-03-17 11:42:53 -04:00
Michael Crenshaw
9c2ffb74c9 fix(ci): handle major versions in compatibility table generator (#22370)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-03-17 11:14:46 -04:00
Regina Voloshin
ab337ed807 docs: promote proxy extensions to beta (#22361)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
2025-03-17 10:05:45 -04:00
1046 changed files with 63527 additions and 41146 deletions

View File

@@ -10,7 +10,7 @@ updates:
groups:
otel:
patterns:
- "^go.opentelemetry.io/.*"
- "go.opentelemetry.io/*"
- package-ecosystem: "github-actions"
directory: "/"
@@ -22,10 +22,11 @@ updates:
schedule:
interval: "daily"
- package-ecosystem: "npm"
directory: "/ui-test/"
schedule:
interval: "daily"
# Disabled since this code is rarely used.
# - package-ecosystem: "npm"
# directory: "/ui-test/"
# schedule:
# interval: "daily"
- package-ecosystem: "docker"
directory: "/"
@@ -52,7 +53,8 @@ updates:
schedule:
interval: "daily"
- package-ecosystem: "docker"
directory: "/ui-test/"
schedule:
interval: "daily"
# Disabled since this code is rarely used.
# - package-ecosystem: "docker"
# directory: "/ui-test/"
# schedule:
# interval: "daily"

View File

@@ -16,7 +16,7 @@
## image-reuse.yaml
- The resuable workflow can be used to publish or build images with multiple container registries(Quay,GHCR, dockerhub), and then sign them with cosign when an image is published.
- The reusable workflow can be used to publish or build images with multiple container registries(Quay,GHCR, dockerhub), and then sign them with cosign when an image is published.
- A GO version `must` be specified e.g. 1.21
- The image name for each registry *must* contain the tag. Note: multiple tags are allowed for each registry using a CSV type.
- Multiple platforms can be specified e.g. linux/amd64,linux/arm64

View File

@@ -37,7 +37,7 @@ jobs:
working-directory: /home/runner/go/src/github.com/argoproj/argo-cd
- name: Setup Golang
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.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@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
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

@@ -14,11 +14,11 @@ on:
env:
# Golang version to use across CI steps
# renovate: datasource=golang-version packageName=golang
GOLANG_VERSION: '1.24.1'
GOLANG_VERSION: '1.24.4'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
permissions:
contents: read
@@ -32,7 +32,7 @@ jobs:
docs: ${{ steps.filter.outputs.docs_any_changed }}
steps:
- uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- uses: tj-actions/changed-files@bab30c2299617f6615ec02a68b9a40d10bd21366 # v45.0.5
- uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.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
@@ -57,7 +57,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- name: Setup Golang
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Download all Go modules
@@ -78,11 +78,11 @@ jobs:
- name: Checkout code
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- name: Setup Golang
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Restore go build cache
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -105,14 +105,14 @@ jobs:
- name: Checkout code
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- name: Setup Golang
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Run golangci-lint
uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1
uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0
with:
# renovate: datasource=go packageName=github.com/golangci/golangci-lint versioning=regex:^v(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)?$
version: v1.64.7
version: v2.1.6
args: --verbose
test-go:
@@ -133,7 +133,7 @@ jobs:
- name: Create symlink in GOPATH
run: ln -s $(pwd) ~/go/src/github.com/argoproj/argo-cd
- name: Setup Golang
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Install required packages
@@ -153,7 +153,7 @@ jobs:
run: |
echo "/usr/local/bin" >> $GITHUB_PATH
- name: Restore go build cache
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -174,7 +174,7 @@ jobs:
- name: Run all unit tests
run: make test-local
- name: Generate test results artifacts
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: test-results
path: test-results
@@ -197,7 +197,7 @@ jobs:
- name: Create symlink in GOPATH
run: ln -s $(pwd) ~/go/src/github.com/argoproj/argo-cd
- name: Setup Golang
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Install required packages
@@ -217,7 +217,7 @@ jobs:
run: |
echo "/usr/local/bin" >> $GITHUB_PATH
- name: Restore go build cache
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -238,7 +238,7 @@ jobs:
- name: Run all unit tests
run: make test-race-local
- name: Generate test results artifacts
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: race-results
path: test-results/
@@ -253,7 +253,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- name: Setup Golang
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Create symlink in GOPATH
@@ -305,13 +305,13 @@ jobs:
- name: Checkout code
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- name: Setup NodeJS
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.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@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: ui/node_modules
key: ${{ runner.os }}-node-dep-v2-${{ hashFiles('**/yarn.lock') }}
@@ -333,6 +333,15 @@ jobs:
run: yarn lint
working-directory: ui/
shellcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- run: |
sudo apt-get install shellcheck
shellcheck -e SC2086 -e SC2046 -e SC2068 -e SC2206 -e SC2048 -e SC2059 -e SC2154 -e SC2034 -e SC2016 -e SC2128 -e SC1091 -e SC2207 $(find . -type f -name '*.sh') | tee sc.log
test ! -s sc.log
analyze:
name: Process & analyze test artifacts
if: ${{ needs.changes.outputs.backend == 'true' || needs.changes.outputs.frontend == 'true' }}
@@ -351,7 +360,7 @@ jobs:
fetch-depth: 0
- name: Restore node dependency cache
id: cache-dependencies
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: ui/node_modules
key: ${{ runner.os }}-node-dep-v2-${{ hashFiles('**/yarn.lock') }}
@@ -359,12 +368,12 @@ jobs:
run: |
rm -rf ui/node_modules/argo-ui/node_modules
- name: Get e2e code coverage
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: e2e-code-coverage
path: e2e-code-coverage
- name: Get unit test code coverage
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: test-results
path: test-results
@@ -376,15 +385,15 @@ jobs:
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
- name: Upload code coverage information to codecov.io
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4.6.0
uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
with:
file: test-results/full-coverage.out
files: test-results/full-coverage.out
fail_ci_if_error: true
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- name: Upload test results to Codecov
if: github.ref == 'refs/heads/master' && github.event_name == 'push' && github.repository == 'argoproj/argo-cd'
uses: codecov/test-results-action@9739113ad922ea0a9abb4b2c0f8bf6a4aa8ef820 # v1.0.1
uses: codecov/test-results-action@47f89e9acb64b76debcd5ea40642d25a4adced9f # v1.1.1
with:
file: test-results/junit.xml
fail_ci_if_error: true
@@ -393,7 +402,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
uses: SonarSource/sonarqube-scan-action@bfd4e558cda28cda6b5defafb9232d191be8c203 # v4.2.1
uses: SonarSource/sonarqube-scan-action@2500896589ef8f7247069a56136f8dc177c27ccf # v5.2.0
if: env.sonar_secret != ''
test-e2e:
name: Run end-to-end tests
@@ -405,14 +414,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.32.1
- version: v1.33.1
latest: true
- version: v1.32.1
latest: false
- version: v1.31.0
latest: false
- version: v1.30.4
latest: false
- version: v1.29.8
latest: false
needs:
- build-go
- changes
@@ -440,7 +449,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- name: Setup Golang
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: GH actions workaround - Kill XSP4 process
@@ -459,7 +468,7 @@ jobs:
sudo chmod go-r $HOME/.kube/config
kubectl version
- name: Restore go build cache
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -485,7 +494,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.41.1
docker pull ghcr.io/dexidp/dex:v2.43.0
docker pull argoproj/argo-cd-ci-builder:v1.0.0
docker pull redis:7.2.7-alpine
- name: Create target directory for binaries in the build-process
@@ -517,13 +526,13 @@ jobs:
goreman run stop-all || echo "goreman trouble"
sleep 30
- name: Upload e2e coverage report
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: e2e-code-coverage
path: /tmp/coverage
if: ${{ matrix.k3s.latest }}
- name: Upload e2e-server logs
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: e2e-server-k8s${{ matrix.k3s.version }}.log
path: /tmp/e2e-server.log

View File

@@ -33,7 +33,7 @@ jobs:
# Use correct go version. https://github.com/github/codeql-action/issues/1842#issuecomment-1704398087
- name: Setup Golang
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version-file: go.mod

View File

@@ -67,15 +67,16 @@ jobs:
if: ${{ github.ref_type != 'tag'}}
- name: Setup Golang
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ inputs.go-version }}
cache: false
- name: Install cosign
uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0
uses: sigstore/cosign-installer@3454372f43399081ed03b604cb2d021dabca52bb # v3.8.2
- uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0
- uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0
- uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
- uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
- name: Setup tags for container image as a CSV type
run: |
@@ -102,7 +103,7 @@ jobs:
echo 'EOF' >> $GITHUB_ENV
- name: Login to Quay.io
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
registry: quay.io
username: ${{ secrets.quay_username }}
@@ -110,7 +111,7 @@ jobs:
if: ${{ inputs.quay_image_name && inputs.push }}
- name: Login to GitHub Container Registry
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
registry: ghcr.io
username: ${{ secrets.ghcr_username }}
@@ -118,7 +119,7 @@ jobs:
if: ${{ inputs.ghcr_image_name && inputs.push }}
- name: Login to dockerhub Container Registry
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
username: ${{ secrets.docker_username }}
password: ${{ secrets.docker_password }}
@@ -141,7 +142,7 @@ jobs:
- name: Build and push container image
id: image
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 #v6.10.0
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 #v6.18.0
with:
context: .
platforms: ${{ inputs.platforms }}

View File

@@ -53,7 +53,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.24.1
go-version: 1.24.4
platforms: ${{ needs.set-vars.outputs.platforms }}
push: false
@@ -70,7 +70,7 @@ jobs:
ghcr_image_name: ghcr.io/argoproj/argo-cd/argocd:${{ needs.set-vars.outputs.image-tag }}
# 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.24.1
go-version: 1.24.4
platforms: ${{ needs.set-vars.outputs.platforms }}
push: true
secrets:
@@ -88,7 +88,7 @@ jobs:
packages: write # for uploading attestations. (https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/container/README.md#known-issues)
if: ${{ github.repository == 'argoproj/argo-cd' && github.event_name == 'push' }}
# Must be refernced by a tag. https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/container/README.md#referencing-the-slsa-generator
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0
with:
image: ghcr.io/argoproj/argo-cd/argocd
digest: ${{ needs.build-and-publish.outputs.image-digest }}

View File

@@ -64,7 +64,7 @@ jobs:
git stash pop
- name: Create pull request
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
with:
commit-message: "Bump version to ${{ inputs.TARGET_VERSION }}"
title: "Bump version to ${{ inputs.TARGET_VERSION }} on ${{ inputs.TARGET_BRANCH }} branch"

View File

@@ -11,7 +11,7 @@ permissions: {}
env:
# renovate: datasource=golang-version packageName=golang
GOLANG_VERSION: '1.24.1' # Note: go-version must also be set in job argocd-image.with.go-version
GOLANG_VERSION: '1.24.4' # Note: go-version must also be set in job argocd-image.with.go-version
jobs:
argocd-image:
@@ -25,7 +25,7 @@ jobs:
quay_image_name: quay.io/argoproj/argocd:${{ github.ref_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.24.1
go-version: 1.24.4
platforms: linux/amd64,linux/arm64,linux/s390x,linux/ppc64le
push: true
secrets:
@@ -40,7 +40,7 @@ jobs:
packages: write # for uploading attestations. (https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/container/README.md#known-issues)
# Must be refernced by a tag. https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/container/README.md#referencing-the-slsa-generator
if: github.repository == 'argoproj/argo-cd'
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0
with:
image: quay.io/argoproj/argocd
digest: ${{ needs.argocd-image.outputs.image-digest }}
@@ -70,14 +70,16 @@ jobs:
run: git fetch --force --tags
- name: Setup Golang
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ env.GOLANG_VERSION }}
cache: false
- name: Set GORELEASER_PREVIOUS_TAG # Workaround, GoReleaser uses 'git-describe' to determine a previous tag. Our tags are created in release branches.
run: |
set -xue
echo "GORELEASER_PREVIOUS_TAG=$(go run hack/get-previous-release/get-previous-version-for-release-notes.go ${{ github.ref_name }})" >> $GITHUB_ENV
GORELEASER_PREVIOUS_TAG=$(go run hack/get-previous-release/get-previous-version-for-release-notes.go ${{ github.ref_name }}) || exit 1
echo "GORELEASER_PREVIOUS_TAG=$GORELEASER_PREVIOUS_TAG" >> $GITHUB_ENV
- name: Set environment variables for ldflags
id: set_ldflag
@@ -94,7 +96,7 @@ jobs:
tool-cache: false
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@9ed2f89a662bf1735a48bc8557fd212fa902bebf # v6.1.0
uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # v6.3.0
id: run-goreleaser
with:
version: latest
@@ -126,7 +128,7 @@ jobs:
contents: write # Needed for release uploads
if: github.repository == 'argoproj/argo-cd'
# Must be refernced by a tag. https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/container/README.md#referencing-the-slsa-generator
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
with:
base64-subjects: '${{ needs.goreleaser.outputs.hashes }}'
provenance-name: 'argocd-cli.intoto.jsonl'
@@ -151,9 +153,10 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Golang
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ env.GOLANG_VERSION }}
cache: false
- name: Generate SBOM (spdx)
id: spdx-builder
@@ -195,7 +198,7 @@ jobs:
echo "hashes=$(sha256sum /tmp/sbom.tar.gz | base64 -w0)" >> "$GITHUB_OUTPUT"
- name: Upload SBOM
uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2.2.1
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8 # v2.3.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
@@ -210,7 +213,7 @@ jobs:
contents: write # Needed for release uploads
if: github.repository == 'argoproj/argo-cd'
# Must be referenced by a tag. https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/container/README.md#referencing-the-slsa-generator
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
with:
base64-subjects: '${{ needs.generate-sbom.outputs.hashes }}'
provenance-name: 'argocd-sbom.intoto.jsonl'
@@ -293,7 +296,7 @@ jobs:
if: ${{ env.UPDATE_VERSION == 'true' }}
- name: Create PR to update VERSION on master branch
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
with:
commit-message: Bump version in master
title: 'chore: Bump version in master'

View File

@@ -35,7 +35,7 @@ jobs:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
with:
results_file: results.sarif
results_format: sarif
@@ -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@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: SARIF file
path: results.sarif

4
.gitignore vendored
View File

@@ -8,6 +8,7 @@ ui/dist/app/*
!ui/dist/app/gitkeep
site/
*.iml
.tilt-bin/
# delve debug binaries
cmd/**/debug
debug.test
@@ -27,3 +28,6 @@ cmd/argocd/argocd
cmd/argocd-application-controller/argocd-application-controller
cmd/argocd-repo-server/argocd-repo-server
cmd/argocd-server/argocd-server
# ignore generated `.argocd-helm-dep-up` marker file; this should not be committed to git
reposerver/repository/testdata/**/.argocd-helm-dep-up

21
.gitpod.Dockerfile vendored
View File

@@ -1,21 +0,0 @@
FROM gitpod/workspace-full@sha256:a47a68ee7f9da10cd889ccce4661bc73f2c0d5a98d3d087e8bdfc0230b27964c
USER root
RUN curl -o /usr/local/bin/kubectl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" && \
chmod +x /usr/local/bin/kubectl
RUN curl -L https://github.com/kubernetes-sigs/kubebuilder/releases/download/v2.3.1/kubebuilder_2.3.1_$(go env GOOS)_$(go env GOARCH).tar.gz | \
tar -xz -C /tmp/ && mv /tmp/kubebuilder_2.3.1_$(go env GOOS)_$(go env GOARCH) /usr/local/kubebuilder
ENV GOCACHE=/go-build-cache
RUN apt-get install redis-server -y
RUN go install github.com/mattn/goreman@latest
RUN chown -R gitpod:gitpod /go-build-cache
USER gitpod
ENV ARGOCD_REDIS_LOCAL=true
ENV KUBECONFIG=/tmp/kubeconfig

View File

@@ -1,6 +0,0 @@
image:
file: .gitpod.Dockerfile
tasks:
- init: make mod-download-local dep-ui-local && GO111MODULE=off go install github.com/mattn/goreman@latest
command: make start-test-k8s

View File

@@ -1,156 +1,253 @@
issues:
exclude:
- SA5011
max-issues-per-linter: 0
max-same-issues: 0
exclude-rules:
- path: '(.+)_test\.go'
linters:
- unparam
linters:
formatters:
enable:
- errcheck
- errorlint
- gocritic
- gofumpt
- goimports
settings:
goimports:
local-prefixes:
- github.com/argoproj/argo-cd/v3
issues:
max-issues-per-linter: 0
max-same-issues: 0
linters:
enable:
- errorlint
- exptostd
- gocritic
- gomodguard
- gosimple
- govet
- importas
- ineffassign
- misspell
# Disabled because of https://github.com/argoproj/argo-cd/issues/21705
# - nolintlint
- perfsprint
- revive
- staticcheck
- testifylint
- thelper
- tparallel
- unparam
- unused
- usestdlibvars
- usetesting
- whitespace
linters-settings:
gocritic:
disabled-checks:
- appendAssign
- assignOp # Keep it disabled for readability
- exitAfterDefer
- mapKey
- typeSwitchVar
goimports:
local-prefixes: github.com/argoproj/argo-cd/v3
gomodguard:
blocked:
modules:
- github.com/golang-jwt/jwt/v4:
recommendations:
- github.com/golang-jwt/jwt/v5
- github.com/imdario/mergo:
recommendations:
- dario.cat/mergo
reason: '`github.com/imdario/mergo` has been renamed.'
- github.com/pkg/errors:
recommendations:
- errors
importas:
alias:
- alias: jwtgo
pkg: github.com/golang-jwt/jwt/v5
- alias: appsv1
pkg: k8s.io/api/apps/v1
- alias: corev1
pkg: k8s.io/api/core/v1
- alias: rbacv1
pkg: k8s.io/api/rbac/v1
- alias: apierrors
pkg: k8s.io/apimachinery/pkg/api/errors
- alias: apiextensionsv1
pkg: k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1
- alias: metav1
pkg: k8s.io/apimachinery/pkg/apis/meta/v1
- alias: informersv1
pkg: k8s.io/client-go/informers/core/v1
- alias: stderrors
pkg: errors
nolintlint:
require-specific: true
perfsprint:
# Optimizes even if it requires an int or uint type cast.
int-conversion: true
# Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.
err-error: true
# Optimizes `fmt.Errorf`.
errorf: true
# Optimizes `fmt.Sprintf` with only one argument.
sprintf1: true
# Optimizes into strings concatenation.
strconcat: true
revive:
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md
exclusions:
rules:
- name: bool-literal-in-expr
- name: blank-imports
disabled: true
- name: context-as-argument
arguments:
- allowTypesBefore: '*testing.T,testing.TB'
- name: context-keys-type
disabled: true
- name: dot-imports
disabled: true
- name: duplicated-imports
- name: early-return
arguments:
- 'preserveScope'
- name: empty-block
disabled: true
- name: error-naming
disabled: true
- name: error-return
- name: error-strings
disabled: true
- name: errorf
- name: identical-branches
- name: if-return
- name: increment-decrement
- name: indent-error-flow
arguments:
- 'preserveScope'
- name: modifies-parameter
- name: optimize-operands-order
- name: range
- name: receiver-naming
- name: redefines-builtin-id
disabled: true
- name: redundant-import-alias
- name: superfluous-else
arguments:
- 'preserveScope'
- name: time-equal
- name: time-naming
disabled: true
- name: unexported-return
disabled: true
- name: unnecessary-stmt
- name: unreachable-code
- name: unused-parameter
- name: use-any
- name: useless-break
- name: var-declaration
- name: var-naming
arguments:
- ["ID"]
- ["VM"]
- - skipPackageNameChecks: true
upperCaseConst: true
testifylint:
enable-all: true
disable:
- go-require
usetesting:
os-mkdir-temp: false
run:
timeout: 50m
- linters:
- unparam
path: (.+)_test\.go
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
warn-unused: true
settings:
gocritic:
enable-all: true
# Most of these should probably be enabled one-by-one.
disabled-checks:
- appendAssign
- appendCombine # Leave disabled, multi-line assigns can be more readable.
- assignOp # Leave disabled, assign operations can be more confusing than helpful.
- commentedOutCode
- deferInLoop
- exitAfterDefer
- exposedSyncMutex
- hugeParam
- importShadow
- paramTypeCombine # Leave disabled, there are too many failures to be worth fixing.
- rangeValCopy
- tooManyResultsChecker
- unnamedResult
- whyNoLint
gomodguard:
blocked:
modules:
- github.com/golang-jwt/jwt/v4:
recommendations:
- github.com/golang-jwt/jwt/v5
- github.com/imdario/mergo:
recommendations:
- dario.cat/mergo
reason: '`github.com/imdario/mergo` has been renamed.'
- github.com/pkg/errors:
recommendations:
- errors
govet:
disable:
- fieldalignment
- shadow
enable-all: true
importas:
alias:
- pkg: github.com/golang-jwt/jwt/v5
alias: jwtgo
- pkg: k8s.io/api/apps/v1
alias: appsv1
- pkg: k8s.io/api/core/v1
alias: corev1
- pkg: k8s.io/api/rbac/v1
alias: rbacv1
- pkg: k8s.io/apimachinery/pkg/api/errors
alias: apierrors
- pkg: k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1
alias: apiextensionsv1
- pkg: k8s.io/apimachinery/pkg/apis/meta/v1
alias: metav1
- pkg: k8s.io/client-go/informers/core/v1
alias: informersv1
- pkg: errors
alias: stderrors
- pkg: github.com/argoproj/argo-cd/v3/util/io
alias: utilio
nolintlint:
require-specific: true
perfsprint:
# Optimizes even if it requires an int or uint type cast.
int-conversion: true
# Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.
err-error: true
# Optimizes `fmt.Errorf`.
errorf: true
# Optimizes `fmt.Sprintf` with only one argument.
sprintf1: true
# Optimizes into strings concatenation.
strconcat: true
revive:
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md
rules:
- name: bool-literal-in-expr
- name: blank-imports
disabled: true
- name: context-as-argument
arguments:
- allowTypesBefore: '*testing.T,testing.TB'
- name: context-keys-type
disabled: true
- name: dot-imports
disabled: true
- name: duplicated-imports
- name: early-return
arguments:
- preserveScope
- name: empty-block
disabled: true
- name: error-naming
disabled: true
- name: error-return
- name: error-strings
disabled: true
- name: errorf
- name: identical-branches
- name: if-return
- name: increment-decrement
- name: indent-error-flow
arguments:
- preserveScope
- name: modifies-parameter
- name: optimize-operands-order
- name: range
- name: receiver-naming
- name: redefines-builtin-id
disabled: true
- name: redundant-import-alias
- name: superfluous-else
arguments:
- preserveScope
- name: time-equal
- name: time-naming
disabled: true
- name: unexported-return
disabled: true
- name: unnecessary-stmt
- name: unreachable-code
- name: unused-parameter
- name: use-any
- name: useless-break
- name: var-declaration
- name: var-naming
arguments:
- - ID
- - VM
- - skipPackageNameChecks: true
upperCaseConst: true
staticcheck:
checks:
- all
- -SA5011
- -ST1003
- -ST1016
testifylint:
enable-all: true
disable:
- go-require
unused:
field-writes-are-uses: false
exported-fields-are-used: false
usetesting:
os-mkdir-temp: false
output:
show-stats: false
version: "2"

View File

@@ -21,11 +21,11 @@ builds:
- -X github.com/argoproj/argo-cd/v3/common.gitCommit={{ .FullCommit }}
- -X github.com/argoproj/argo-cd/v3/common.gitTreeState={{ .Env.GIT_TREE_STATE }}
- -X github.com/argoproj/argo-cd/v3/common.kubectlVersion={{ .Env.KUBECTL_VERSION }}
- -extldflags="-static"
- '{{ if or (eq .Runtime.Goos "linux") (eq .Runtime.Goos "windows") }}-extldflags="-static"{{ end }}'
goos:
- linux
- darwin
- windows
- darwin
goarch:
- amd64
- arm64
@@ -42,14 +42,23 @@ builds:
goarch: ppc64le
- goos: windows
goarch: arm64
overrides:
- goos: darwin
goarch: amd64
env:
- CGO_ENABLED=1
- goos: darwin
goarch: arm64
env:
- CGO_ENABLED=1
archives:
- id: argocd-archive
builds:
- argocd-cli
ids:
- argocd-cli
name_template: |-
{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}
format: binary
formats: [ binary ]
checksum:
name_template: 'cli_checksums.txt'
@@ -80,26 +89,27 @@ release:
All Argo CD container images are signed by cosign. A Provenance is generated for container images and CLI binaries which meet the SLSA Level 3 specifications. See the [documentation](https://argo-cd.readthedocs.io/en/stable/operator-manual/signed-release-assets) on how to verify.
## Release Notes Blog Post
For a detailed breakdown of the key changes and improvements in this release, check out the [official blog post](https://blog.argoproj.io/argo-cd-v2-14-release-candidate-57a664791e2a)
For a detailed breakdown of the key changes and improvements in this release, check out the [official blog post](https://blog.argoproj.io/argo-cd-v3-0-release-candidate-a0b933f4e58f)
## Upgrading
If upgrading from a different minor version, be sure to read the [upgrading](https://argo-cd.readthedocs.io/en/stable/operator-manual/upgrading/overview/) documentation.
footer: |
**Full Changelog**: https://github.com/argoproj/argo-cd/compare/{{ .PreviousTag }}...{{ .Tag }}
<a href="https://argoproj.github.io/cd/"><img src="https://raw.githubusercontent.com/argoproj/argo-site/master/content/pages/cd/gitops-cd.png" width="25%" ></a>
snapshot: #### To be removed for PR
name_template: "2.6.0"
version_template: '2.6.0'
changelog:
use:
github
use: github
sort: asc
abbrev: 0
groups: # Regex use RE2 syntax as defined here: https://github.com/google/re2/wiki/Syntax.
- title: 'Breaking Changes'
regexp: '^.*?(\([[:word:]]+\))??!:.+$'
order: 0
- title: 'Features'
regexp: '^.*?feat(\([[:word:]]+\))??!?:.+$'
order: 100
@@ -119,7 +129,4 @@ changelog:
- '^test:'
- '^.*?Bump(\([[:word:]]+\))?.+$'
- '^.*?\[Bot\](\([[:word:]]+\))?.+$'
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json

View File

@@ -1,82 +1,82 @@
# global config
filename: "{{.InterfaceName}}.go"
dir: "{{.InterfaceDir}}/mocks"
outpkg: "mocks"
mockname: "{{.InterfaceName}}"
with-expecter: false
# individual interface config
dir: '{{.InterfaceDir}}/mocks'
structname: '{{.InterfaceName}}'
filename: '{{.InterfaceName}}.go'
pkgname: mocks
template-data:
unroll-variadic: true
packages:
github.com/argoproj/argo-cd/v3/applicationset/generators:
interfaces:
Generator:
Generator: {}
github.com/argoproj/argo-cd/v3/applicationset/services:
interfaces:
Repos:
Repos: {}
github.com/argoproj/argo-cd/v3/applicationset/services/scm_provider:
config:
dir: "applicationset/services/scm_provider/aws_codecommit/mocks"
dir: applicationset/services/scm_provider/aws_codecommit/mocks
interfaces:
AWSCodeCommitClient:
AWSTaggingClient:
github.com/microsoft/azure-devops-go-api/azuredevops/git:
config:
dir: "applicationset/services/scm_provider/azure_devops/git/mocks"
interfaces:
Client:
AWSCodeCommitClient: {}
AWSTaggingClient: {}
github.com/argoproj/argo-cd/v3/applicationset/utils:
interfaces:
Renderer:
github.com/argoproj/argo-cd/v3/commitserver/commit:
interfaces:
RepoClientFactory:
Renderer: {}
github.com/argoproj/argo-cd/v3/commitserver/apiclient:
interfaces:
CommitServiceClient:
Clientset:
Clientset: {}
CommitServiceClient: {}
github.com/argoproj/argo-cd/v3/commitserver/commit:
interfaces:
RepoClientFactory: {}
github.com/argoproj/argo-cd/v3/controller/cache:
interfaces:
LiveStateCache:
github.com/argoproj/argo-cd/v3/reposerver/apiclient:
interfaces:
RepoServerServiceClient:
RepoServerService_GenerateManifestWithFilesClient:
github.com/argoproj/argo-cd/v3/server/application:
interfaces:
Broadcaster:
github.com/argoproj/argo-cd/v3/server/extension:
interfaces:
ApplicationGetter:
ExtensionMetricsRegistry:
ProjectGetter:
RbacEnforcer:
SettingsGetter:
UserGetter:
github.com/argoproj/argo-cd/v3/util/db:
interfaces:
ArgoDB:
github.com/argoproj/argo-cd/v3/util/git:
interfaces:
Client:
github.com/argoproj/argo-cd/v3/util/helm:
interfaces:
Client:
github.com/argoproj/argo-cd/v3/util/io:
interfaces:
TempPaths:
github.com/argoproj/argo-cd/v3/util/notification/argocd:
interfaces:
Service:
github.com/argoproj/argo-cd/v3/util/workloadidentity:
interfaces:
TokenProvider:
# These mocks are not currently used, but they are part of the public API of this package.
github.com/argoproj/argo-cd/v3/pkg/apiclient/session:
interfaces:
SessionServiceServer:
SessionServiceClient:
LiveStateCache: {}
github.com/argoproj/argo-cd/v3/pkg/apiclient/cluster:
interfaces:
ClusterServiceServer:
ClusterServiceServer: {}
github.com/argoproj/argo-cd/v3/pkg/apiclient/session:
interfaces:
SessionServiceClient: {}
SessionServiceServer: {}
github.com/argoproj/argo-cd/v3/pkg/client/clientset/versioned/typed/application/v1alpha1:
interfaces:
AppProjectInterface:
AppProjectInterface: {}
github.com/argoproj/argo-cd/v3/reposerver/apiclient:
interfaces:
RepoServerService_GenerateManifestWithFilesClient: {}
RepoServerServiceClient: {}
github.com/argoproj/argo-cd/v3/server/application:
interfaces:
Broadcaster: {}
github.com/argoproj/argo-cd/v3/server/extension:
interfaces:
ApplicationGetter: {}
ExtensionMetricsRegistry: {}
ProjectGetter: {}
RbacEnforcer: {}
SettingsGetter: {}
UserGetter: {}
github.com/argoproj/argo-cd/v3/util/db:
interfaces:
ArgoDB: {}
github.com/argoproj/argo-cd/v3/util/git:
interfaces:
Client: {}
github.com/argoproj/argo-cd/v3/util/helm:
interfaces:
Client: {}
github.com/argoproj/argo-cd/v3/util/io:
interfaces:
TempPaths: {}
github.com/argoproj/argo-cd/v3/util/notification/argocd:
interfaces:
Service: {}
github.com/argoproj/argo-cd/v3/util/workloadidentity:
interfaces:
TokenProvider: {}
github.com/microsoft/azure-devops-go-api/azuredevops/v7/git:
config:
dir: applicationset/services/scm_provider/azure_devops/git/mocks
interfaces:
Client: {}

View File

@@ -4,7 +4,7 @@ ARG BASE_IMAGE=docker.io/library/ubuntu:24.04@sha256:80dd3c3b9c6cecb9f1667e9290b
# 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.24.1@sha256:c5adecdb7b3f8c5ca3c88648a861882849cc8b02fed68ece31e25de88ad13418 AS builder
FROM docker.io/library/golang:1.24.4@sha256:db5d0afbfb4ab648af2393b92e87eaae9ad5e01132803d80caef91b5752d289c AS builder
WORKDIR /tmp
@@ -103,7 +103,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.24.1@sha256:c5adecdb7b3f8c5ca3c88648a861882849cc8b02fed68ece31e25de88ad13418 AS argocd-build
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.24.4@sha256:db5d0afbfb4ab648af2393b92e87eaae9ad5e01132803d80caef91b5752d289c AS argocd-build
WORKDIR /go/src/github.com/argoproj/argo-cd

62
Dockerfile.tilt Normal file
View File

@@ -0,0 +1,62 @@
FROM docker.io/library/golang:1.24.1@sha256:c5adecdb7b3f8c5ca3c88648a861882849cc8b02fed68ece31e25de88ad13418
ENV DEBIAN_FRONTEND=noninteractive
RUN echo 'deb http://archive.debian.org/debian buster-backports main' >> /etc/apt/sources.list
RUN apt-get update && apt-get install --no-install-recommends -y \
curl \
openssh-server \
nginx \
unzip \
fcgiwrap \
git \
git-lfs \
make \
wget \
gcc \
sudo \
zip \
tini \
gpg \
tzdata \
connect-proxy
RUN go install github.com/go-delve/delve/cmd/dlv@latest
COPY hack/install.sh hack/tool-versions.sh ./
COPY hack/installers installers
RUN ./install.sh helm && \
INSTALL_PATH=/usr/local/bin ./install.sh kustomize
COPY hack/gpg-wrapper.sh \
hack/git-verify-wrapper.sh \
entrypoint.sh \
/usr/local/bin/
# support for mounting configuration from a configmap
WORKDIR /app/config/ssh
RUN touch ssh_known_hosts && \
ln -s /app/config/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts
WORKDIR /app/config
RUN mkdir -p tls && \
mkdir -p gpg/source && \
mkdir -p gpg/keys
COPY .tilt-bin/argocd_linux /usr/local/bin/argocd
RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-server && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-repo-server && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-application-controller && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-dex && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-notifications && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-applicationset-controller && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-commit-server
# directory for Tilt restart file
RUN mkdir -p /tilt
# overridden by Tiltfile
ENTRYPOINT ["/usr/bin/tini", "-s", "--", "dlv", "exec", "--continue", "--accept-multiclient", "--headless", "--listen=:2345", "--api-version=2"]

9
Dockerfile.ui.tilt Normal file
View File

@@ -0,0 +1,9 @@
FROM node:24
WORKDIR /app/ui
COPY ui /app/ui
RUN yarn install
ENTRYPOINT ["yarn", "start"]

View File

@@ -3,7 +3,16 @@ CURRENT_DIR=$(shell pwd)
DIST_DIR=${CURRENT_DIR}/dist
CLI_NAME=argocd
BIN_NAME=argocd
CGO_FLAG=0
UNAME_S:=$(shell uname)
IS_DARWIN:=$(if $(filter Darwin, $(UNAME_S)),true,false)
# When using OSX/Darwin, you might need to enable CGO for local builds
DEFAULT_CGO_FLAG:=0
ifeq ($(IS_DARWIN),true)
DEFAULT_CGO_FLAG:=1
endif
CGO_FLAG?=${DEFAULT_CGO_FLAG}
GEN_RESOURCES_CLI_NAME=argocd-resources-gen
@@ -147,7 +156,11 @@ PATH:=$(PATH):$(PWD)/hack
DOCKER_PUSH?=false
IMAGE_NAMESPACE?=
# perform static compilation
STATIC_BUILD?=true
DEFAULT_STATIC_BUILD:=true
ifeq ($(IS_DARWIN),true)
DEFAULT_STATIC_BUILD:=false
endif
STATIC_BUILD?=${DEFAULT_STATIC_BUILD}
# build development images
DEV_IMAGE?=false
ARGOCD_GPG_ENABLED?=true
@@ -486,6 +499,7 @@ start-e2e-local: mod-vendor-local dep-ui-local cli-local
ARGOCD_APPLICATIONSET_CONTROLLER_ALLOWED_SCM_PROVIDERS=http://127.0.0.1:8341,http://127.0.0.1:8342,http://127.0.0.1:8343,http://127.0.0.1:8344 \
ARGOCD_E2E_TEST=true \
ARGOCD_HYDRATOR_ENABLED=true \
ARGOCD_CLUSTER_CACHE_EVENTS_PROCESSING_INTERVAL=1ms \
goreman -f $(ARGOCD_PROCFILE) start ${ARGOCD_START}
ls -lrt /tmp/coverage
@@ -584,6 +598,7 @@ install-test-tools-local:
./hack/install.sh kustomize
./hack/install.sh helm
./hack/install.sh gotestsum
./hack/install.sh oras
# Installs all tools required for running codegen (Linux packages)
.PHONY: install-codegen-tools-local

View File

@@ -8,6 +8,7 @@ commit-server: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go
ui: sh -c 'cd ui && ${ARGOCD_E2E_YARN_CMD:-yarn} start'
git-server: test/fixture/testrepos/start-git.sh
helm-registry: test/fixture/testrepos/start-helm-registry.sh
oci-registry: test/fixture/testrepos/start-authenticated-helm-registry.sh
dev-mounter: [[ "$ARGOCD_E2E_TEST" != "true" ]] && go run hack/dev-mounter/main.go --configmap argocd-ssh-known-hosts-cm=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} --configmap argocd-tls-certs-cm=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} --configmap argocd-gpg-keys-cm=${ARGOCD_GPG_DATA_PATH:-/tmp/argocd-local/gpg/source}
applicationset-controller: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "GOCOVERDIR=${ARGOCD_COVERAGE_DIR:-/tmp/coverage/applicationset-controller} FORCE_LOG_COLORS=4 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-applicationset-controller $COMMAND --loglevel debug --metrics-addr localhost:12345 --probe-addr localhost:12346 --argocd-repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081}"
notification: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "GOCOVERDIR=${ARGOCD_COVERAGE_DIR:-/tmp/coverage/notification} FORCE_LOG_COLORS=4 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_BINARY_NAME=argocd-notifications $COMMAND --loglevel debug --application-namespaces=${ARGOCD_APPLICATION_NAMESPACES:-''} --self-service-notification-enabled=${ARGOCD_NOTIFICATION_CONTROLLER_SELF_SERVICE_NOTIFICATION_ENABLED:-'false'}"

View File

@@ -3,9 +3,9 @@ header:
expiration-date: '2024-10-31T00:00:00.000Z' # One year from initial release.
last-updated: '2023-10-27'
last-reviewed: '2023-10-27'
commit-hash: 74a367d10e7110209610ba3ec225539ebe5f7522
commit-hash: 226a670fe6b3c6769ff6d18e6839298a58e4577d
project-url: https://github.com/argoproj/argo-cd
project-release: v2.14.0
project-release: v3.1.0
changelog: https://github.com/argoproj/argo-cd/releases
license: https://github.com/argoproj/argo-cd/blob/master/LICENSE
project-lifecycle:

282
Tiltfile Normal file
View File

@@ -0,0 +1,282 @@
load('ext://restart_process', 'docker_build_with_restart')
load('ext://uibutton', 'cmd_button', 'location')
# add ui button in web ui to run make codegen-local (top nav)
cmd_button(
'make codegen-local',
argv=['sh', '-c', 'make codegen-local'],
location=location.NAV,
icon_name='terminal',
text='make codegen-local',
)
# add ui button in web ui to run make codegen-local (top nav)
cmd_button(
'make cli-local',
argv=['sh', '-c', 'make cli-local'],
location=location.NAV,
icon_name='terminal',
text='make cli-local',
)
# detect cluster architecture for build
cluster_version = decode_yaml(local('kubectl version -o yaml'))
platform = cluster_version['serverVersion']['platform']
arch = platform.split('/')[1]
# build the argocd binary on code changes
code_deps = [
'applicationset',
'cmd',
'cmpserver',
'commitserver',
'common',
'controller',
'notification-controller',
'pkg',
'reposerver',
'server',
'util',
'go.mod',
'go.sum',
]
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,
allow_parallel=True,
)
# deploy the argocd manifests
k8s_yaml(kustomize('manifests/dev-tilt'))
# build dev image
docker_build_with_restart(
'argocd',
context='.',
dockerfile='Dockerfile.tilt',
entrypoint=[
"/usr/bin/tini",
"-s",
"--",
"dlv",
"exec",
"--continue",
"--accept-multiclient",
"--headless",
"--listen=:2345",
"--api-version=2"
],
platform=platform,
live_update=[
sync('.tilt-bin/argocd_linux_amd64', '/usr/local/bin/argocd'),
],
only=[
'.tilt-bin',
'hack',
'entrypoint.sh',
],
restart_file='/tilt/.restart-proc'
)
# build image for argocd-cli jobs
docker_build(
'argocd-job',
context='.',
dockerfile='Dockerfile.tilt',
platform=platform,
only=[
'.tilt-bin',
'hack',
'entrypoint.sh',
]
)
# track argocd-server resources and port forward
k8s_resource(
workload='argocd-server',
objects=[
'argocd-server:serviceaccount',
'argocd-server:role',
'argocd-server:rolebinding',
'argocd-cm:configmap',
'argocd-cmd-params-cm:configmap',
'argocd-gpg-keys-cm:configmap',
'argocd-rbac-cm:configmap',
'argocd-ssh-known-hosts-cm:configmap',
'argocd-tls-certs-cm:configmap',
'argocd-secret:secret',
'argocd-server-network-policy:networkpolicy',
'argocd-server:clusterrolebinding',
'argocd-server:clusterrole',
],
port_forwards=[
'8080:8080',
'9345:2345',
'8083:8083'
],
)
# track crds
k8s_resource(
new_name='cluster-resources',
objects=[
'applications.argoproj.io:customresourcedefinition',
'applicationsets.argoproj.io:customresourcedefinition',
'appprojects.argoproj.io:customresourcedefinition',
'argocd:namespace'
]
)
# track argocd-repo-server resources and port forward
k8s_resource(
workload='argocd-repo-server',
objects=[
'argocd-repo-server:serviceaccount',
'argocd-repo-server-network-policy:networkpolicy',
],
port_forwards=[
'8081:8081',
'9346:2345',
'8084:8084'
],
)
# track argocd-redis resources and port forward
k8s_resource(
workload='argocd-redis',
objects=[
'argocd-redis:serviceaccount',
'argocd-redis:role',
'argocd-redis:rolebinding',
'argocd-redis-network-policy:networkpolicy',
],
port_forwards=[
'6379:6379',
],
)
# track argocd-applicationset-controller resources
k8s_resource(
workload='argocd-applicationset-controller',
objects=[
'argocd-applicationset-controller:serviceaccount',
'argocd-applicationset-controller-network-policy:networkpolicy',
'argocd-applicationset-controller:role',
'argocd-applicationset-controller:rolebinding',
'argocd-applicationset-controller:clusterrolebinding',
'argocd-applicationset-controller:clusterrole',
],
port_forwards=[
'9347:2345',
'8085:8080',
'7000:7000'
],
)
# track argocd-application-controller resources
k8s_resource(
workload='argocd-application-controller',
objects=[
'argocd-application-controller:serviceaccount',
'argocd-application-controller-network-policy:networkpolicy',
'argocd-application-controller:role',
'argocd-application-controller:rolebinding',
'argocd-application-controller:clusterrolebinding',
'argocd-application-controller:clusterrole',
],
port_forwards=[
'9348:2345',
'8086:8082',
],
)
# track argocd-notifications-controller resources
k8s_resource(
workload='argocd-notifications-controller',
objects=[
'argocd-notifications-controller:serviceaccount',
'argocd-notifications-controller-network-policy:networkpolicy',
'argocd-notifications-controller:role',
'argocd-notifications-controller:rolebinding',
'argocd-notifications-cm:configmap',
'argocd-notifications-secret:secret',
],
port_forwards=[
'9349:2345',
'8087:9001',
],
)
# track argocd-dex-server resources
k8s_resource(
workload='argocd-dex-server',
objects=[
'argocd-dex-server:serviceaccount',
'argocd-dex-server-network-policy:networkpolicy',
'argocd-dex-server:role',
'argocd-dex-server:rolebinding',
],
)
# track argocd-commit-server resources
k8s_resource(
workload='argocd-commit-server',
objects=[
'argocd-commit-server:serviceaccount',
'argocd-commit-server-network-policy:networkpolicy',
],
port_forwards=[
'9350:2345',
'8088:8087',
'8089:8086',
],
)
# docker for ui
docker_build(
'argocd-ui',
context='.',
dockerfile='Dockerfile.ui.tilt',
entrypoint=['sh', '-c', 'cd /app/ui && yarn start'],
only=['ui'],
live_update=[
sync('ui', '/app/ui'),
run('sh -c "cd /app/ui && yarn install"', trigger=['/app/ui/package.json', '/app/ui/yarn.lock']),
],
)
# track argocd-ui resources and port forward
k8s_resource(
workload='argocd-ui',
port_forwards=[
'4000:4000',
],
)
# linting
local_resource(
'lint',
'make lint-local',
deps = code_deps,
allow_parallel=True,
)
local_resource(
'lint-ui',
'make lint-ui-local',
deps = [
'ui',
],
allow_parallel=True,
)
local_resource(
'vendor',
'go mod vendor',
deps = [
'go.mod',
'go.sum',
],
)

View File

@@ -30,6 +30,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Ant Group](https://www.antgroup.com/)
1. [AppDirect](https://www.appdirect.com)
1. [Arctiq Inc.](https://www.arctiq.ca)
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/)
1. [Augury](https://www.augury.com/)
@@ -45,6 +46,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Bedag Informatik AG](https://www.bedag.ch/)
1. [Beleza Na Web](https://www.belezanaweb.com.br/)
1. [Believable Bots](https://believablebots.io)
1. [Bayer AG](https://bayer.com)
1. [BigPanda](https://bigpanda.io)
1. [BioBox Analytics](https://biobox.io)
1. [BMW Group](https://www.bmwgroup.com/)
@@ -67,6 +69,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Chainnodes](https://chainnodes.org)
1. [Chargetrip](https://chargetrip.com)
1. [Chime](https://www.chime.com)
1. [Chronicle Labs](https://chroniclelabs.org)
1. [Cisco ET&I](https://eti.cisco.com/)
1. [Cloud Posse](https://www.cloudposse.com/)
1. [Cloud Scale](https://cloudscaleinc.com/)
@@ -92,12 +95,15 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Daydream](https://daydream.ing)
1. [Deloitte](https://www.deloitte.com/)
1. [Deutsche Telekom AG](https://telekom.com)
1. [Deutsche Bank AG](https://www.deutsche-bank.de/)
1. [Devopsi - Poland Software/DevOps Consulting](https://devopsi.pl/)
1. [Devtron Labs](https://github.com/devtron-labs/devtron)
1. [DigitalEd](https://www.digitaled.com)
1. [DigitalOcean](https://www.digitalocean.com)
1. [Divar](https://divar.ir)
1. [Divistant](https://divistant.com)
1. [Dott](https://ridedott.com)
1. [Doubble](https://www.doubble.app)
1. [Doximity](https://www.doximity.com/)
1. [EDF Renewables](https://www.edf-re.com/)
1. [edX](https://edx.org)
@@ -109,6 +115,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Energisme](https://energisme.com/)
1. [enigmo](https://enigmo.co.jp/)
1. [Envoy](https://envoy.com/)
1. [eSave](https://esave.es/)
1. [Factorial](https://factorialhr.com/)
1. [Farfetch](https://www.farfetch.com)
1. [Faro](https://www.faro.com/)
@@ -156,6 +163,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [IABAI](https://www.iab.ai)
1. [IBM](https://www.ibm.com/)
1. [Ibotta](https://home.ibotta.com)
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)
@@ -259,6 +267,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Patreon](https://www.patreon.com/)
1. [PayIt](https://payitgov.com/)
1. [PayPay](https://paypay.ne.jp/)
1. [Paystack](https://paystack.com/)
1. [Peloton Interactive](https://www.onepeloton.com/)
1. [Percona](https://percona.com/)
1. [PGS](https://www.pgs.com)
@@ -305,6 +314,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Saloodo! GmbH](https://www.saloodo.com)
1. [Sap Labs](http://sap.com)
1. [Sauce Labs](https://saucelabs.com/)
1. [Schneider Electric](https://www.se.com)
1. [Schwarz IT](https://jobs.schwarz/it-mission)
1. [SCRM Lidl International Hub](https://scrm.lidl)
1. [SEEK](https://seek.com.au)
@@ -314,7 +324,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [SI Analytics](https://si-analytics.ai)
1. [Sidewalk Entertainment](https://sidewalkplay.com/)
1. [Skit](https://skit.ai/)
1. [Skribble](https://skribble.com)
1. [Skribble](https://skribble.com)
1. [Skyscanner](https://www.skyscanner.net/)
1. [Smart Pension](https://www.smartpension.co.uk/)
1. [Smilee.io](https://smilee.io)
@@ -335,11 +345,13 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Sumo Logic](https://sumologic.com/)
1. [Sutpc](http://www.sutpc.com/)
1. [Swiss Post](https://github.com/swisspost)
1. [Swissblock Technologies](https://swissblock.net/)
1. [Swisscom](https://www.swisscom.ch)
1. [Swissquote](https://github.com/swissquote)
1. [Syncier](https://syncier.com/)
1. [Synergy](https://synergy.net.au)
1. [Syself](https://syself.com)
1. [T-ROC Global](https://trocglobal.com/)
1. [TableCheck](https://tablecheck.com/)
1. [Tailor Brands](https://www.tailorbrands.com)
1. [Tamkeen Technologies](https://tamkeentech.sa/)
@@ -381,6 +393,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Volvo Cars](https://www.volvocars.com/)
1. [Voyager Digital](https://www.investvoyager.com/)
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. [Wehkamp](https://www.wehkamp.nl/)
@@ -396,8 +409,8 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Yieldlab](https://www.yieldlab.de/)
1. [Youverify](https://youverify.co/)
1. [Yubo](https://www.yubo.live/)
1. [Yuno](https://y.uno/)
1. [ZDF](https://www.zdf.de/)
1. [Zimpler](https://www.zimpler.com/)
1. [ZipRecuiter](https://www.ziprecruiter.com/)
1. [ZipRecruiter](https://www.ziprecruiter.com/)
1. [ZOZO](https://corp.zozo.com/)

View File

@@ -1 +1 @@
3.0.0
3.1.0

View File

@@ -51,6 +51,7 @@ import (
"github.com/argoproj/argo-cd/v3/applicationset/status"
"github.com/argoproj/argo-cd/v3/applicationset/utils"
"github.com/argoproj/argo-cd/v3/common"
applog "github.com/argoproj/argo-cd/v3/util/app/log"
"github.com/argoproj/argo-cd/v3/util/db"
argov1alpha1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
@@ -127,8 +128,8 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}()
// Do not attempt to further reconcile the ApplicationSet if it is being deleted.
if applicationSetInfo.ObjectMeta.DeletionTimestamp != nil {
appsetName := applicationSetInfo.ObjectMeta.Name
if applicationSetInfo.DeletionTimestamp != nil {
appsetName := applicationSetInfo.Name
logCtx.Debugf("DeletionTimestamp is set on %s", appsetName)
deleteAllowed := utils.DefaultPolicy(applicationSetInfo.Spec.SyncPolicy, r.Policy, r.EnablePolicyOverride).AllowDelete()
if !deleteAllowed {
@@ -210,16 +211,16 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
appSyncMap := map[string]bool{}
if r.EnableProgressiveSyncs {
if applicationSetInfo.Spec.Strategy == nil && len(applicationSetInfo.Status.ApplicationStatus) > 0 {
// If appset used progressive sync but stopped, clean up the progressive sync application statuses
if !isRollingSyncStrategy(&applicationSetInfo) && len(applicationSetInfo.Status.ApplicationStatus) > 0 {
// If an appset was previously syncing with a `RollingSync` strategy but it has switched to the default strategy, clean up the progressive sync application statuses
logCtx.Infof("Removing %v unnecessary AppStatus entries from ApplicationSet %v", len(applicationSetInfo.Status.ApplicationStatus), applicationSetInfo.Name)
err := r.setAppSetApplicationStatus(ctx, logCtx, &applicationSetInfo, []argov1alpha1.ApplicationSetApplicationStatus{})
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to clear previous AppSet application statuses for %v: %w", applicationSetInfo.Name, err)
}
} else if applicationSetInfo.Spec.Strategy != nil {
// appset uses progressive sync
} else if isRollingSyncStrategy(&applicationSetInfo) {
// The appset uses progressive sync with `RollingSync` strategy
for _, app := range currentApplications {
appMap[app.Name] = app
}
@@ -314,7 +315,7 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
if applicationSetInfo.RefreshRequired() {
delete(applicationSetInfo.Annotations, common.AnnotationApplicationSetRefresh)
err := r.Client.Update(ctx, &applicationSetInfo)
err := r.Update(ctx, &applicationSetInfo)
if err != nil {
logCtx.Warnf("error occurred while updating ApplicationSet: %v", err)
_ = r.setApplicationSetStatusCondition(ctx,
@@ -488,7 +489,7 @@ func (r *ApplicationSetReconciler) validateGeneratedApplications(ctx context.Con
namesSet[app.Name] = true
appProject := &argov1alpha1.AppProject{}
err := r.Client.Get(ctx, types.NamespacedName{Name: app.Spec.Project, Namespace: r.ArgoCDNamespace}, appProject)
err := r.Get(ctx, types.NamespacedName{Name: app.Spec.Project, Namespace: r.ArgoCDNamespace}, appProject)
if err != nil {
if apierrors.IsNotFound(err) {
errorsByIndex[i] = fmt.Errorf("application references project %s which does not exist", app.Spec.Project)
@@ -553,7 +554,7 @@ func (r *ApplicationSetReconciler) SetupWithManager(mgr ctrl.Manager, enableProg
}
appOwnsHandler := getApplicationOwnsHandler(enableProgressiveSyncs)
appSetOwnsHandler := getApplicationSetOwnsHandler()
appSetOwnsHandler := getApplicationSetOwnsHandler(enableProgressiveSyncs)
return ctrl.NewControllerManagedBy(mgr).WithOptions(controller.Options{
MaxConcurrentReconciles: maxConcurrentReconciliations,
@@ -577,7 +578,7 @@ func (r *ApplicationSetReconciler) createOrUpdateInCluster(ctx context.Context,
var firstError error
// Creates or updates the application in appList
for _, generatedApp := range desiredApplications {
appLog := logCtx.WithFields(log.Fields{"app": generatedApp.QualifiedName()})
appLog := logCtx.WithFields(applog.GetAppLogFields(&generatedApp))
// Normalize to avoid fighting with the application controller.
generatedApp.Spec = *argoutil.NormalizeApplicationSpec(&generatedApp.Spec)
@@ -624,7 +625,7 @@ func (r *ApplicationSetReconciler) createOrUpdateInCluster(ctx context.Context,
preservedAnnotations = append(preservedAnnotations, defaultPreservedAnnotations...)
for _, key := range preservedAnnotations {
if state, exists := found.ObjectMeta.Annotations[key]; exists {
if state, exists := found.Annotations[key]; exists {
if generatedApp.Annotations == nil {
generatedApp.Annotations = map[string]string{}
}
@@ -633,7 +634,7 @@ func (r *ApplicationSetReconciler) createOrUpdateInCluster(ctx context.Context,
}
for _, key := range preservedLabels {
if state, exists := found.ObjectMeta.Labels[key]; exists {
if state, exists := found.Labels[key]; exists {
if generatedApp.Labels == nil {
generatedApp.Labels = map[string]string{}
}
@@ -643,7 +644,7 @@ func (r *ApplicationSetReconciler) createOrUpdateInCluster(ctx context.Context,
// Preserve post-delete finalizers:
// https://github.com/argoproj/argo-cd/issues/17181
for _, finalizer := range found.ObjectMeta.Finalizers {
for _, finalizer := range found.Finalizers {
if strings.HasPrefix(finalizer, argov1alpha1.PostDeleteFinalizerName) {
if generatedApp.Finalizers == nil {
generatedApp.Finalizers = []string{}
@@ -652,10 +653,10 @@ func (r *ApplicationSetReconciler) createOrUpdateInCluster(ctx context.Context,
}
}
found.ObjectMeta.Annotations = generatedApp.Annotations
found.Annotations = generatedApp.Annotations
found.ObjectMeta.Finalizers = generatedApp.Finalizers
found.ObjectMeta.Labels = generatedApp.Labels
found.Finalizers = generatedApp.Finalizers
found.Labels = generatedApp.Labels
return controllerutil.SetControllerReference(&applicationSet, found, r.Scheme)
})
@@ -709,7 +710,7 @@ func (r *ApplicationSetReconciler) createInCluster(ctx context.Context, logCtx *
func (r *ApplicationSetReconciler) getCurrentApplications(ctx context.Context, applicationSet argov1alpha1.ApplicationSet) ([]argov1alpha1.Application, error) {
var current argov1alpha1.ApplicationList
err := r.Client.List(ctx, &current, client.MatchingFields{".metadata.controller": applicationSet.Name}, client.InNamespace(applicationSet.Namespace))
err := r.List(ctx, &current, client.MatchingFields{".metadata.controller": applicationSet.Name}, client.InNamespace(applicationSet.Namespace))
if err != nil {
return nil, fmt.Errorf("error retrieving applications: %w", err)
}
@@ -740,7 +741,7 @@ func (r *ApplicationSetReconciler) deleteInCluster(ctx context.Context, logCtx *
// Delete apps that are not in m[string]bool
var firstError error
for _, app := range current {
logCtx = logCtx.WithField("app", app.QualifiedName())
logCtx = logCtx.WithFields(applog.GetAppLogFields(&app))
_, exists := m[app.Name]
if !exists {
@@ -754,7 +755,7 @@ func (r *ApplicationSetReconciler) deleteInCluster(ctx context.Context, logCtx *
continue
}
err = r.Client.Delete(ctx, &app)
err = r.Delete(ctx, &app)
if err != nil {
logCtx.WithError(err).Error("failed to delete Application")
if firstError != nil {
@@ -823,7 +824,7 @@ func (r *ApplicationSetReconciler) removeFinalizerOnInvalidDestination(ctx conte
if log.IsLevelEnabled(log.DebugLevel) {
utils.LogPatch(appLog, patch, updated)
}
if err := r.Client.Patch(ctx, updated, patch); err != nil {
if err := r.Patch(ctx, updated, patch); err != nil {
return fmt.Errorf("error updating finalizers: %w", err)
}
// Application must have updated list of finalizers
@@ -845,7 +846,7 @@ func (r *ApplicationSetReconciler) removeOwnerReferencesOnDeleteAppSet(ctx conte
for _, app := range applications {
app.SetOwnerReferences([]metav1.OwnerReference{})
err := r.Client.Update(ctx, &app)
err := r.Update(ctx, &app)
if err != nil {
return fmt.Errorf("error updating application: %w", err)
}
@@ -1000,8 +1001,14 @@ func appSyncEnabledForNextStep(appset *argov1alpha1.ApplicationSet, app argov1al
return true
}
func isRollingSyncStrategy(appset *argov1alpha1.ApplicationSet) bool {
// It's only RollingSync if the type specifically sets it
return appset.Spec.Strategy != nil && appset.Spec.Strategy.Type == "RollingSync" && appset.Spec.Strategy.RollingSync != nil
}
func progressiveSyncsRollingSyncStrategyEnabled(appset *argov1alpha1.ApplicationSet) bool {
return appset.Spec.Strategy != nil && appset.Spec.Strategy.RollingSync != nil && appset.Spec.Strategy.Type == "RollingSync" && len(appset.Spec.Strategy.RollingSync.Steps) > 0
// ProgressiveSync is enabled if the strategy is set to `RollingSync` + steps slice is not empty
return isRollingSyncStrategy(appset) && len(appset.Spec.Strategy.RollingSync.Steps) > 0
}
func isApplicationHealthy(app argov1alpha1.Application) bool {
@@ -1398,7 +1405,7 @@ func (r *ApplicationSetReconciler) syncValidApplications(logCtx *log.Entry, appl
pruneEnabled := false
// 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 validApps[i].Spec.SyncPolicy != nil && validApps[i].Spec.SyncPolicy.Automated != nil {
if validApps[i].Spec.SyncPolicy != nil && validApps[i].Spec.SyncPolicy.IsAutomatedSyncEnabled() {
pruneEnabled = validApps[i].Spec.SyncPolicy.Automated.Prune
validApps[i].Spec.SyncPolicy.Automated = nil
}
@@ -1434,6 +1441,10 @@ func syncApplication(application argov1alpha1.Application, prune bool) argov1alp
},
},
Sync: &argov1alpha1.SyncOperation{},
// Set a retry limit of 5, aligning with the default in Argo CD's appcontroller auto-sync behavior.
// This provides consistency for retry behavior across controllers.
// See: https://github.com/argoproj/argo-cd/blob/af9ebac0bb35dc16eb034c1cefaf7c92d1029927/controller/appcontroller.go#L2126
Retry: argov1alpha1.RetryStrategy{Limit: 5},
}
if application.Spec.SyncPolicy != nil {
@@ -1456,23 +1467,23 @@ func getApplicationOwnsHandler(enableProgressiveSyncs bool) predicate.Funcs {
// if we are the owner and there is a create event, we most likely created it and do not need to
// re-reconcile
if log.IsLevelEnabled(log.DebugLevel) {
var appName string
logFields := log.Fields{"app": ""}
app, isApp := e.Object.(*argov1alpha1.Application)
if isApp {
appName = app.QualifiedName()
logFields = applog.GetAppLogFields(app)
}
log.WithField("app", appName).Debugln("received create event from owning an application")
log.WithFields(logFields).Debugln("received create event from owning an application")
}
return false
},
DeleteFunc: func(e event.DeleteEvent) bool {
if log.IsLevelEnabled(log.DebugLevel) {
var appName string
logFields := log.Fields{"app": ""}
app, isApp := e.Object.(*argov1alpha1.Application)
if isApp {
appName = app.QualifiedName()
logFields = applog.GetAppLogFields(app)
}
log.WithField("app", appName).Debugln("received delete event from owning an application")
log.WithFields(logFields).Debugln("received delete event from owning an application")
}
return true
},
@@ -1481,7 +1492,7 @@ func getApplicationOwnsHandler(enableProgressiveSyncs bool) predicate.Funcs {
if !isApp {
return false
}
logCtx := log.WithField("app", appOld.QualifiedName())
logCtx := log.WithFields(applog.GetAppLogFields(appOld))
logCtx.Debugln("received update event from owning an application")
appNew, isApp := e.ObjectNew.(*argov1alpha1.Application)
if !isApp {
@@ -1493,12 +1504,12 @@ func getApplicationOwnsHandler(enableProgressiveSyncs bool) predicate.Funcs {
},
GenericFunc: func(e event.GenericEvent) bool {
if log.IsLevelEnabled(log.DebugLevel) {
var appName string
logFields := log.Fields{}
app, isApp := e.Object.(*argov1alpha1.Application)
if isApp {
appName = app.QualifiedName()
logFields = applog.GetAppLogFields(app)
}
log.WithField("app", appName).Debugln("received generic event from owning an application")
log.WithFields(logFields).Debugln("received generic event from owning an application")
}
return true
},
@@ -1521,9 +1532,9 @@ func shouldRequeueForApplication(appOld *argov1alpha1.Application, appNew *argov
// https://pkg.go.dev/reflect#DeepEqual
// ApplicationDestination has an unexported field so we can just use the == for comparison
if !cmp.Equal(appOld.Spec, appNew.Spec, cmpopts.EquateEmpty(), cmpopts.EquateComparable(argov1alpha1.ApplicationDestination{})) ||
!cmp.Equal(appOld.ObjectMeta.GetAnnotations(), appNew.ObjectMeta.GetAnnotations(), cmpopts.EquateEmpty()) ||
!cmp.Equal(appOld.ObjectMeta.GetLabels(), appNew.ObjectMeta.GetLabels(), cmpopts.EquateEmpty()) ||
!cmp.Equal(appOld.ObjectMeta.GetFinalizers(), appNew.ObjectMeta.GetFinalizers(), cmpopts.EquateEmpty()) {
!cmp.Equal(appOld.GetAnnotations(), appNew.GetAnnotations(), cmpopts.EquateEmpty()) ||
!cmp.Equal(appOld.GetLabels(), appNew.GetLabels(), cmpopts.EquateEmpty()) ||
!cmp.Equal(appOld.GetFinalizers(), appNew.GetFinalizers(), cmpopts.EquateEmpty()) {
return true
}
@@ -1544,7 +1555,7 @@ func shouldRequeueForApplication(appOld *argov1alpha1.Application, appNew *argov
return false
}
func getApplicationSetOwnsHandler() predicate.Funcs {
func getApplicationSetOwnsHandler(enableProgressiveSyncs bool) predicate.Funcs {
return predicate.Funcs{
CreateFunc: func(e event.CreateEvent) bool {
appSet, isApp := e.Object.(*argov1alpha1.ApplicationSet)
@@ -1573,7 +1584,7 @@ func getApplicationSetOwnsHandler() predicate.Funcs {
if !isAppSet {
return false
}
requeue := shouldRequeueForApplicationSet(appSetOld, appSetNew)
requeue := shouldRequeueForApplicationSet(appSetOld, appSetNew, enableProgressiveSyncs)
log.WithField("applicationset", appSetNew.QualifiedName()).
WithField("requeue", requeue).Debugln("received update event")
return requeue
@@ -1591,24 +1602,32 @@ func getApplicationSetOwnsHandler() predicate.Funcs {
}
// shouldRequeueForApplicationSet determines when we need to requeue an applicationset
func shouldRequeueForApplicationSet(appSetOld, appSetNew *argov1alpha1.ApplicationSet) bool {
func shouldRequeueForApplicationSet(appSetOld, appSetNew *argov1alpha1.ApplicationSet, enableProgressiveSyncs bool) bool {
if appSetOld == nil || appSetNew == nil {
return false
}
// Requeue if any ApplicationStatus.Status changed for Progressive sync strategy
if enableProgressiveSyncs {
if !cmp.Equal(appSetOld.Status.ApplicationStatus, appSetNew.Status.ApplicationStatus, cmpopts.EquateEmpty()) {
return true
}
}
// only compare the applicationset spec, annotations, labels and finalizers, specifically avoiding
// the status field. status is owned by the applicationset controller,
// and we do not need to requeue when it does bookkeeping
// NB: the ApplicationDestination comes from the ApplicationSpec being embedded
// in the ApplicationSetTemplate from the generators
if !cmp.Equal(appSetOld.Spec, appSetNew.Spec, cmpopts.EquateEmpty(), cmpopts.EquateComparable(argov1alpha1.ApplicationDestination{})) ||
!cmp.Equal(appSetOld.ObjectMeta.GetLabels(), appSetNew.ObjectMeta.GetLabels(), cmpopts.EquateEmpty()) ||
!cmp.Equal(appSetOld.ObjectMeta.GetFinalizers(), appSetNew.ObjectMeta.GetFinalizers(), cmpopts.EquateEmpty()) {
!cmp.Equal(appSetOld.GetLabels(), appSetNew.GetLabels(), cmpopts.EquateEmpty()) ||
!cmp.Equal(appSetOld.GetFinalizers(), appSetNew.GetFinalizers(), cmpopts.EquateEmpty()) {
return true
}
// Requeue only when the refresh annotation is newly added to the ApplicationSet.
// Changes to other annotations made simultaneously might be missed, but such cases are rare.
if !cmp.Equal(appSetOld.ObjectMeta.GetAnnotations(), appSetNew.ObjectMeta.GetAnnotations(), cmpopts.EquateEmpty()) {
if !cmp.Equal(appSetOld.GetAnnotations(), appSetNew.GetAnnotations(), cmpopts.EquateEmpty()) {
_, oldHasRefreshAnnotation := appSetOld.Annotations[common.AnnotationApplicationSetRefresh]
_, newHasRefreshAnnotation := appSetNew.Annotations[common.AnnotationApplicationSetRefresh]

View File

@@ -36,6 +36,7 @@ import (
argocommon "github.com/argoproj/argo-cd/v3/common"
"github.com/argoproj/argo-cd/v3/pkg/apis/application"
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
applog "github.com/argoproj/argo-cd/v3/util/app/log"
"github.com/argoproj/argo-cd/v3/util/db"
"github.com/argoproj/argo-cd/v3/util/settings"
)
@@ -1210,7 +1211,7 @@ func TestRemoveFinalizerOnInvalidDestination_FinalizerTypes(t *testing.T) {
clusterList, err := utils.ListClusters(t.Context(), kubeclientset, "namespace")
require.NoError(t, err)
appLog := log.WithFields(log.Fields{"app": app.Name, "appSet": ""})
appLog := log.WithFields(applog.GetAppLogFields(&app)).WithField("appSet", "")
appInputParam := app.DeepCopy()
@@ -1366,7 +1367,7 @@ func TestRemoveFinalizerOnInvalidDestination_DestinationTypes(t *testing.T) {
clusterList, err := utils.ListClusters(t.Context(), kubeclientset, "argocd")
require.NoError(t, err)
appLog := log.WithFields(log.Fields{"app": app.Name, "appSet": ""})
appLog := log.WithFields(applog.GetAppLogFields(&app)).WithField("appSet", "")
appInputParam := app.DeepCopy()
@@ -2184,12 +2185,12 @@ func TestReconcilerValidationProjectErrorBehaviour(t *testing.T) {
var app v1alpha1.Application
// make sure good app got created
err = r.Client.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "good-project"}, &app)
err = r.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "good-project"}, &app)
require.NoError(t, err)
assert.Equal(t, "good-project", app.Name)
// make sure bad app was not created
err = r.Client.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "bad-project"}, &app)
err = r.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "bad-project"}, &app)
require.Error(t, err)
}
@@ -2472,13 +2473,13 @@ func applicationsUpdateSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp
var app v1alpha1.Application
// make sure good app got created
err = r.Client.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "good-cluster"}, &app)
err = r.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "good-cluster"}, &app)
require.NoError(t, err)
assert.Equal(t, "good-cluster", app.Name)
// Update resource
var retrievedApplicationSet v1alpha1.ApplicationSet
err = r.Client.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "name"}, &retrievedApplicationSet)
err = r.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "name"}, &retrievedApplicationSet)
require.NoError(t, err)
retrievedApplicationSet.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
@@ -2488,13 +2489,13 @@ func applicationsUpdateSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp
Values: "global.test: test",
}
err = r.Client.Update(t.Context(), &retrievedApplicationSet)
err = r.Update(t.Context(), &retrievedApplicationSet)
require.NoError(t, err)
resUpdate, err := r.Reconcile(t.Context(), req)
require.NoError(t, err)
err = r.Client.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "good-cluster"}, &app)
err = r.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "good-cluster"}, &app)
require.NoError(t, err)
assert.Equal(t, time.Duration(0), resUpdate.RequeueAfter)
assert.Equal(t, "good-cluster", app.Name)
@@ -2508,7 +2509,7 @@ func TestUpdateNotPerformedWithSyncPolicyCreateOnly(t *testing.T) {
app := applicationsUpdateSyncPolicyTest(t, applicationsSyncPolicy, 1, true)
assert.Nil(t, app.Spec.Source.Helm)
assert.Nil(t, app.ObjectMeta.Annotations)
assert.Nil(t, app.Annotations)
}
func TestUpdateNotPerformedWithSyncPolicyCreateDelete(t *testing.T) {
@@ -2517,7 +2518,7 @@ func TestUpdateNotPerformedWithSyncPolicyCreateDelete(t *testing.T) {
app := applicationsUpdateSyncPolicyTest(t, applicationsSyncPolicy, 1, true)
assert.Nil(t, app.Spec.Source.Helm)
assert.Nil(t, app.ObjectMeta.Annotations)
assert.Nil(t, app.Annotations)
}
func TestUpdatePerformedWithSyncPolicyCreateUpdate(t *testing.T) {
@@ -2526,8 +2527,8 @@ func TestUpdatePerformedWithSyncPolicyCreateUpdate(t *testing.T) {
app := applicationsUpdateSyncPolicyTest(t, applicationsSyncPolicy, 2, true)
assert.Equal(t, "global.test: test", app.Spec.Source.Helm.Values)
assert.Equal(t, map[string]string{"annotation-key": "annotation-value"}, app.ObjectMeta.Annotations)
assert.Equal(t, map[string]string{"label-key": "label-value"}, app.ObjectMeta.Labels)
assert.Equal(t, map[string]string{"annotation-key": "annotation-value"}, app.Annotations)
assert.Equal(t, map[string]string{"label-key": "label-value"}, app.Labels)
}
func TestUpdatePerformedWithSyncPolicySync(t *testing.T) {
@@ -2536,8 +2537,8 @@ func TestUpdatePerformedWithSyncPolicySync(t *testing.T) {
app := applicationsUpdateSyncPolicyTest(t, applicationsSyncPolicy, 2, true)
assert.Equal(t, "global.test: test", app.Spec.Source.Helm.Values)
assert.Equal(t, map[string]string{"annotation-key": "annotation-value"}, app.ObjectMeta.Annotations)
assert.Equal(t, map[string]string{"label-key": "label-value"}, app.ObjectMeta.Labels)
assert.Equal(t, map[string]string{"annotation-key": "annotation-value"}, app.Annotations)
assert.Equal(t, map[string]string{"label-key": "label-value"}, app.Labels)
}
func TestUpdatePerformedWithSyncPolicyCreateOnlyAndAllowPolicyOverrideFalse(t *testing.T) {
@@ -2546,8 +2547,8 @@ func TestUpdatePerformedWithSyncPolicyCreateOnlyAndAllowPolicyOverrideFalse(t *t
app := applicationsUpdateSyncPolicyTest(t, applicationsSyncPolicy, 2, false)
assert.Equal(t, "global.test: test", app.Spec.Source.Helm.Values)
assert.Equal(t, map[string]string{"annotation-key": "annotation-value"}, app.ObjectMeta.Annotations)
assert.Equal(t, map[string]string{"label-key": "label-value"}, app.ObjectMeta.Labels)
assert.Equal(t, map[string]string{"annotation-key": "annotation-value"}, app.Annotations)
assert.Equal(t, map[string]string{"label-key": "label-value"}, app.Labels)
}
func applicationsDeleteSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alpha1.ApplicationsSyncPolicy, recordBuffer int, allowPolicyOverride bool) v1alpha1.ApplicationList {
@@ -2647,13 +2648,13 @@ func applicationsDeleteSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp
var app v1alpha1.Application
// make sure good app got created
err = r.Client.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "good-cluster"}, &app)
err = r.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "good-cluster"}, &app)
require.NoError(t, err)
assert.Equal(t, "good-cluster", app.Name)
// Update resource
var retrievedApplicationSet v1alpha1.ApplicationSet
err = r.Client.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "name"}, &retrievedApplicationSet)
err = r.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "name"}, &retrievedApplicationSet)
require.NoError(t, err)
retrievedApplicationSet.Spec.Generators = []v1alpha1.ApplicationSetGenerator{
{
@@ -2663,7 +2664,7 @@ func applicationsDeleteSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp
},
}
err = r.Client.Update(t.Context(), &retrievedApplicationSet)
err = r.Update(t.Context(), &retrievedApplicationSet)
require.NoError(t, err)
resUpdate, err := r.Reconcile(t.Context(), req)
@@ -2671,7 +2672,7 @@ func applicationsDeleteSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp
var apps v1alpha1.ApplicationList
err = r.Client.List(t.Context(), &apps)
err = r.List(t.Context(), &apps)
require.NoError(t, err)
assert.Equal(t, time.Duration(0), resUpdate.RequeueAfter)
@@ -2833,20 +2834,20 @@ func TestPolicies(t *testing.T) {
assert.Equal(t, time.Duration(0), res.RequeueAfter)
var app v1alpha1.Application
err = r.Client.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "my-app"}, &app)
err = r.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "my-app"}, &app)
require.NoError(t, err)
assert.Equal(t, "value", app.Annotations["key"])
// Check if Application is updated
app.Annotations["key"] = "edited"
err = r.Client.Update(t.Context(), &app)
err = r.Update(t.Context(), &app)
require.NoError(t, err)
res, err = r.Reconcile(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, time.Duration(0), res.RequeueAfter)
err = r.Client.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "my-app"}, &app)
err = r.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "my-app"}, &app)
require.NoError(t, err)
if c.allowedUpdate {
@@ -2856,21 +2857,21 @@ func TestPolicies(t *testing.T) {
}
// Check if Application is deleted
err = r.Client.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "name"}, &appSet)
err = r.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "name"}, &appSet)
require.NoError(t, err)
appSet.Spec.Generators[0] = v1alpha1.ApplicationSetGenerator{
List: &v1alpha1.ListGenerator{
Elements: []apiextensionsv1.JSON{},
},
}
err = r.Client.Update(t.Context(), &appSet)
err = r.Update(t.Context(), &appSet)
require.NoError(t, err)
res, err = r.Reconcile(t.Context(), req)
require.NoError(t, err)
assert.Equal(t, time.Duration(0), res.RequeueAfter)
err = r.Client.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "my-app"}, &app)
err = r.Get(t.Context(), crtclient.ObjectKey{Namespace: "argocd", Name: "my-app"}, &app)
require.NoError(t, err)
if c.allowedDelete {
assert.NotNil(t, app.DeletionTimestamp)
@@ -3887,7 +3888,7 @@ func TestBuildAppSyncMap(t *testing.T) {
Name: "app1",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -3903,7 +3904,7 @@ func TestBuildAppSyncMap(t *testing.T) {
Name: "app2",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -3965,7 +3966,7 @@ func TestBuildAppSyncMap(t *testing.T) {
Name: "app1",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -3981,7 +3982,7 @@ func TestBuildAppSyncMap(t *testing.T) {
Name: "app2",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -4043,7 +4044,7 @@ func TestBuildAppSyncMap(t *testing.T) {
Name: "app1",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -4059,7 +4060,7 @@ func TestBuildAppSyncMap(t *testing.T) {
Name: "app2",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -4121,7 +4122,7 @@ func TestBuildAppSyncMap(t *testing.T) {
Name: "app1",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusDegraded,
},
OperationState: &v1alpha1.OperationState{
@@ -4137,7 +4138,7 @@ func TestBuildAppSyncMap(t *testing.T) {
Name: "app2",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusDegraded,
},
OperationState: &v1alpha1.OperationState{
@@ -4203,7 +4204,7 @@ func TestBuildAppSyncMap(t *testing.T) {
Name: "app1",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -4219,7 +4220,7 @@ func TestBuildAppSyncMap(t *testing.T) {
Name: "app2",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -4293,7 +4294,7 @@ func TestBuildAppSyncMap(t *testing.T) {
Name: "app1",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -4309,7 +4310,7 @@ func TestBuildAppSyncMap(t *testing.T) {
Name: "app2",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -4325,7 +4326,7 @@ func TestBuildAppSyncMap(t *testing.T) {
Name: "app3",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -4341,7 +4342,7 @@ func TestBuildAppSyncMap(t *testing.T) {
Name: "app5",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -4357,7 +4358,7 @@ func TestBuildAppSyncMap(t *testing.T) {
Name: "app6",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusDegraded,
},
OperationState: &v1alpha1.OperationState{
@@ -4475,7 +4476,7 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
Name: "app1",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -4530,7 +4531,7 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
Name: "app1",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -4594,7 +4595,7 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
Name: "app1",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -4745,7 +4746,7 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
Name: "app1",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusProgressing,
},
Sync: v1alpha1.SyncStatus{
@@ -4807,7 +4808,7 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
Name: "app1",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -4873,7 +4874,7 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
Name: "app1",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -4939,7 +4940,7 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
Name: "app1",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -4994,7 +4995,7 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
Name: "app1",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -5067,7 +5068,7 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
Name: "app1",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusDegraded,
},
OperationState: &v1alpha1.OperationState{
@@ -5148,7 +5149,7 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
Name: "app1",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusDegraded,
},
OperationState: &v1alpha1.OperationState{
@@ -5233,7 +5234,7 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
Name: "app1",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -5299,7 +5300,7 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
Name: "app1",
},
Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
OperationState: &v1alpha1.OperationState{
@@ -6155,9 +6156,8 @@ func TestUpdateResourceStatus(t *testing.T) {
Sync: v1alpha1.SyncStatus{
Status: v1alpha1.SyncStatusCodeSynced,
},
Health: v1alpha1.HealthStatus{
Status: health.HealthStatusHealthy,
Message: "OK",
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
},
},
@@ -6167,8 +6167,7 @@ func TestUpdateResourceStatus(t *testing.T) {
Name: "app1",
Status: v1alpha1.SyncStatusCodeSynced,
Health: &v1alpha1.HealthStatus{
Status: health.HealthStatusHealthy,
Message: "OK",
Status: health.HealthStatusHealthy,
},
},
},
@@ -6186,8 +6185,7 @@ func TestUpdateResourceStatus(t *testing.T) {
Name: "app1",
Status: v1alpha1.SyncStatusCodeSynced,
Health: &v1alpha1.HealthStatus{
Status: health.HealthStatusHealthy,
Message: "OK",
Status: health.HealthStatusHealthy,
},
},
},
@@ -6202,9 +6200,8 @@ func TestUpdateResourceStatus(t *testing.T) {
Sync: v1alpha1.SyncStatus{
Status: v1alpha1.SyncStatusCodeSynced,
},
Health: v1alpha1.HealthStatus{
Status: health.HealthStatusHealthy,
Message: "OK",
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
},
},
@@ -6214,8 +6211,7 @@ func TestUpdateResourceStatus(t *testing.T) {
Name: "app1",
Status: v1alpha1.SyncStatusCodeSynced,
Health: &v1alpha1.HealthStatus{
Status: health.HealthStatusHealthy,
Message: "OK",
Status: health.HealthStatusHealthy,
},
},
},
@@ -6249,9 +6245,8 @@ func TestUpdateResourceStatus(t *testing.T) {
Sync: v1alpha1.SyncStatus{
Status: v1alpha1.SyncStatusCodeSynced,
},
Health: v1alpha1.HealthStatus{
Status: health.HealthStatusHealthy,
Message: "OK",
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
},
},
@@ -6261,8 +6256,7 @@ func TestUpdateResourceStatus(t *testing.T) {
Name: "app1",
Status: v1alpha1.SyncStatusCodeSynced,
Health: &v1alpha1.HealthStatus{
Status: health.HealthStatusHealthy,
Message: "OK",
Status: health.HealthStatusHealthy,
},
},
},
@@ -6324,8 +6318,7 @@ func generateNAppResourceStatuses(n int) []v1alpha1.ResourceStatus {
Name: "app" + strconv.Itoa(i),
Status: v1alpha1.SyncStatusCodeSynced,
Health: &v1alpha1.HealthStatus{
Status: health.HealthStatusHealthy,
Message: "OK",
Status: health.HealthStatusHealthy,
},
},
)
@@ -6344,9 +6337,8 @@ func generateNHealthyApps(n int) []v1alpha1.Application {
Sync: v1alpha1.SyncStatus{
Status: v1alpha1.SyncStatusCodeSynced,
},
Health: v1alpha1.HealthStatus{
Status: health.HealthStatusHealthy,
Message: "OK",
Health: v1alpha1.AppHealthStatus{
Status: health.HealthStatusHealthy,
},
},
})
@@ -6450,12 +6442,12 @@ func TestApplicationOwnsHandler(t *testing.T) {
{name: "ApplicationHealthStatusDiff", args: args{
e: event.UpdateEvent{
ObjectOld: &v1alpha1.Application{Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: "Unknown",
},
}},
ObjectNew: &v1alpha1.Application{Status: v1alpha1.ApplicationStatus{
Health: v1alpha1.HealthStatus{
Health: v1alpha1.AppHealthStatus{
Status: "Healthy",
},
}},
@@ -6678,8 +6670,6 @@ func TestMigrateStatus(t *testing.T) {
}
func TestApplicationSetOwnsHandlerUpdate(t *testing.T) {
ownsHandler := getApplicationSetOwnsHandler()
buildAppSet := func(annotations map[string]string) *v1alpha1.ApplicationSet {
return &v1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
@@ -6689,10 +6679,11 @@ func TestApplicationSetOwnsHandlerUpdate(t *testing.T) {
}
tests := []struct {
name string
appSetOld crtclient.Object
appSetNew crtclient.Object
want bool
name string
appSetOld crtclient.Object
appSetNew crtclient.Object
enableProgressiveSyncs bool
want bool
}{
{
name: "Different Spec",
@@ -6710,13 +6701,15 @@ func TestApplicationSetOwnsHandlerUpdate(t *testing.T) {
},
},
},
want: true,
enableProgressiveSyncs: false,
want: true,
},
{
name: "Different Annotations",
appSetOld: buildAppSet(map[string]string{"key1": "value1"}),
appSetNew: buildAppSet(map[string]string{"key1": "value2"}),
want: true,
name: "Different Annotations",
appSetOld: buildAppSet(map[string]string{"key1": "value1"}),
appSetNew: buildAppSet(map[string]string{"key1": "value2"}),
enableProgressiveSyncs: false,
want: true,
},
{
name: "Different Labels",
@@ -6730,7 +6723,8 @@ func TestApplicationSetOwnsHandlerUpdate(t *testing.T) {
Labels: map[string]string{"key1": "value2"},
},
},
want: true,
enableProgressiveSyncs: false,
want: true,
},
{
name: "Different Finalizers",
@@ -6744,7 +6738,8 @@ func TestApplicationSetOwnsHandlerUpdate(t *testing.T) {
Finalizers: []string{"finalizer2"},
},
},
want: true,
enableProgressiveSyncs: false,
want: true,
},
{
name: "No Changes",
@@ -6772,15 +6767,17 @@ func TestApplicationSetOwnsHandlerUpdate(t *testing.T) {
Finalizers: []string{"finalizer1"},
},
},
want: false,
enableProgressiveSyncs: false,
want: false,
},
{
name: "annotation removed",
appSetOld: buildAppSet(map[string]string{
argocommon.AnnotationApplicationSetRefresh: "true",
}),
appSetNew: buildAppSet(map[string]string{}),
want: false,
appSetNew: buildAppSet(map[string]string{}),
enableProgressiveSyncs: false,
want: false,
},
{
name: "annotation not removed",
@@ -6790,7 +6787,8 @@ func TestApplicationSetOwnsHandlerUpdate(t *testing.T) {
appSetNew: buildAppSet(map[string]string{
argocommon.AnnotationApplicationSetRefresh: "true",
}),
want: false,
enableProgressiveSyncs: false,
want: false,
},
{
name: "annotation added",
@@ -6798,35 +6796,39 @@ func TestApplicationSetOwnsHandlerUpdate(t *testing.T) {
appSetNew: buildAppSet(map[string]string{
argocommon.AnnotationApplicationSetRefresh: "true",
}),
want: true,
enableProgressiveSyncs: false,
want: true,
},
{
name: "old object is not an appset",
appSetOld: &v1alpha1.Application{},
appSetNew: buildAppSet(map[string]string{}),
want: false,
name: "old object is not an appset",
appSetOld: &v1alpha1.Application{},
appSetNew: buildAppSet(map[string]string{}),
enableProgressiveSyncs: false,
want: false,
},
{
name: "new object is not an appset",
appSetOld: buildAppSet(map[string]string{}),
appSetNew: &v1alpha1.Application{},
want: false,
name: "new object is not an appset",
appSetOld: buildAppSet(map[string]string{}),
appSetNew: &v1alpha1.Application{},
enableProgressiveSyncs: false,
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ownsHandler := getApplicationSetOwnsHandler(tt.enableProgressiveSyncs)
requeue := ownsHandler.UpdateFunc(event.UpdateEvent{
ObjectOld: tt.appSetOld,
ObjectNew: tt.appSetNew,
})
assert.Equalf(t, tt.want, requeue, "ownsHandler.UpdateFunc(%v, %v)", tt.appSetOld, tt.appSetNew)
assert.Equalf(t, tt.want, requeue, "ownsHandler.UpdateFunc(%v, %v, %t)", tt.appSetOld, tt.appSetNew, tt.enableProgressiveSyncs)
})
}
}
func TestApplicationSetOwnsHandlerGeneric(t *testing.T) {
ownsHandler := getApplicationSetOwnsHandler()
ownsHandler := getApplicationSetOwnsHandler(false)
tests := []struct {
name string
obj crtclient.Object
@@ -6855,7 +6857,7 @@ func TestApplicationSetOwnsHandlerGeneric(t *testing.T) {
}
func TestApplicationSetOwnsHandlerCreate(t *testing.T) {
ownsHandler := getApplicationSetOwnsHandler()
ownsHandler := getApplicationSetOwnsHandler(false)
tests := []struct {
name string
obj crtclient.Object
@@ -6884,7 +6886,7 @@ func TestApplicationSetOwnsHandlerCreate(t *testing.T) {
}
func TestApplicationSetOwnsHandlerDelete(t *testing.T) {
ownsHandler := getApplicationSetOwnsHandler()
ownsHandler := getApplicationSetOwnsHandler(false)
tests := []struct {
name string
obj crtclient.Object
@@ -6914,19 +6916,55 @@ func TestApplicationSetOwnsHandlerDelete(t *testing.T) {
func TestShouldRequeueForApplicationSet(t *testing.T) {
type args struct {
appSetOld *v1alpha1.ApplicationSet
appSetNew *v1alpha1.ApplicationSet
appSetOld *v1alpha1.ApplicationSet
appSetNew *v1alpha1.ApplicationSet
enableProgressiveSyncs bool
}
tests := []struct {
name string
args args
want bool
}{
{name: "NilAppSet", args: args{appSetNew: &v1alpha1.ApplicationSet{}, appSetOld: nil}, want: false},
{
name: "NilAppSet",
args: args{
appSetNew: &v1alpha1.ApplicationSet{},
appSetOld: nil,
enableProgressiveSyncs: false,
},
want: false,
},
{
name: "ApplicationSetApplicationStatusChanged",
args: args{
appSetOld: &v1alpha1.ApplicationSet{
Status: v1alpha1.ApplicationSetStatus{
ApplicationStatus: []v1alpha1.ApplicationSetApplicationStatus{
{
Application: "app1",
Status: "Healthy",
},
},
},
},
appSetNew: &v1alpha1.ApplicationSet{
Status: v1alpha1.ApplicationSetStatus{
ApplicationStatus: []v1alpha1.ApplicationSetApplicationStatus{
{
Application: "app1",
Status: "Waiting",
},
},
},
},
enableProgressiveSyncs: true,
},
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equalf(t, tt.want, shouldRequeueForApplicationSet(tt.args.appSetOld, tt.args.appSetNew), "shouldRequeueForApplicationSet(%v, %v)", tt.args.appSetOld, tt.args.appSetNew)
assert.Equalf(t, tt.want, shouldRequeueForApplicationSet(tt.args.appSetOld, tt.args.appSetNew, tt.args.enableProgressiveSyncs), "shouldRequeueForApplicationSet(%v, %v)", tt.args.appSetOld, tt.args.appSetNew)
})
}
}
@@ -7013,3 +7051,150 @@ func TestIgnoreNotAllowedNamespaces(t *testing.T) {
})
}
}
func TestIsRollingSyncStrategy(t *testing.T) {
tests := []struct {
name string
appset *v1alpha1.ApplicationSet
expected bool
}{
{
name: "RollingSync strategy is explicitly set",
appset: &v1alpha1.ApplicationSet{
Spec: v1alpha1.ApplicationSetSpec{
Strategy: &v1alpha1.ApplicationSetStrategy{
Type: "RollingSync",
RollingSync: &v1alpha1.ApplicationSetRolloutStrategy{
Steps: []v1alpha1.ApplicationSetRolloutStep{},
},
},
},
},
expected: true,
},
{
name: "AllAtOnce strategy is explicitly set",
appset: &v1alpha1.ApplicationSet{
Spec: v1alpha1.ApplicationSetSpec{
Strategy: &v1alpha1.ApplicationSetStrategy{
Type: "AllAtOnce",
},
},
},
expected: false,
},
{
name: "Strategy is empty",
appset: &v1alpha1.ApplicationSet{
Spec: v1alpha1.ApplicationSetSpec{
Strategy: &v1alpha1.ApplicationSetStrategy{},
},
},
expected: false,
},
{
name: "Strategy is nil",
appset: &v1alpha1.ApplicationSet{
Spec: v1alpha1.ApplicationSetSpec{
Strategy: nil,
},
},
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := isRollingSyncStrategy(tt.appset)
assert.Equal(t, tt.expected, result)
})
}
}
func TestSyncApplication(t *testing.T) {
tests := []struct {
name string
input v1alpha1.Application
prune bool
expected v1alpha1.Application
}{
{
name: "Default retry limit with no SyncPolicy",
input: v1alpha1.Application{
Spec: v1alpha1.ApplicationSpec{},
},
prune: false,
expected: v1alpha1.Application{
Spec: v1alpha1.ApplicationSpec{},
Operation: &v1alpha1.Operation{
InitiatedBy: v1alpha1.OperationInitiator{
Username: "applicationset-controller",
Automated: true,
},
Info: []*v1alpha1.Info{
{
Name: "Reason",
Value: "ApplicationSet RollingSync triggered a sync of this Application resource.",
},
},
Sync: &v1alpha1.SyncOperation{
Prune: false,
},
Retry: v1alpha1.RetryStrategy{
Limit: 5,
},
},
},
},
{
name: "Retry and SyncOptions from SyncPolicy are applied",
input: v1alpha1.Application{
Spec: v1alpha1.ApplicationSpec{
SyncPolicy: &v1alpha1.SyncPolicy{
Retry: &v1alpha1.RetryStrategy{
Limit: 10,
},
SyncOptions: []string{"CreateNamespace=true"},
},
},
},
prune: true,
expected: v1alpha1.Application{
Spec: v1alpha1.ApplicationSpec{
SyncPolicy: &v1alpha1.SyncPolicy{
Retry: &v1alpha1.RetryStrategy{
Limit: 10,
},
SyncOptions: []string{"CreateNamespace=true"},
},
},
Operation: &v1alpha1.Operation{
InitiatedBy: v1alpha1.OperationInitiator{
Username: "applicationset-controller",
Automated: true,
},
Info: []*v1alpha1.Info{
{
Name: "Reason",
Value: "ApplicationSet RollingSync triggered a sync of this Application resource.",
},
},
Sync: &v1alpha1.SyncOperation{
SyncOptions: []string{"CreateNamespace=true"},
Prune: true,
},
Retry: v1alpha1.RetryStrategy{
Limit: 10,
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := syncApplication(tt.input, tt.prune)
assert.Equal(t, tt.expected, result)
})
}
}

View File

@@ -20,6 +20,15 @@ import (
argov1alpha1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
)
type mockAddRateLimitingInterface struct {
addedItems []reconcile.Request
}
// Add checks the type, and adds it to the internal list of received additions
func (obj *mockAddRateLimitingInterface) Add(item reconcile.Request) {
obj.addedItems = append(obj.addedItems, item)
}
func TestClusterEventHandler(t *testing.T) {
scheme := runtime.NewScheme()
err := argov1alpha1.AddToScheme(scheme)
@@ -556,15 +565,6 @@ func TestClusterEventHandler(t *testing.T) {
}
}
// Add checks the type, and adds it to the internal list of received additions
func (obj *mockAddRateLimitingInterface) Add(item reconcile.Request) {
obj.addedItems = append(obj.addedItems, item)
}
type mockAddRateLimitingInterface struct {
addedItems []reconcile.Request
}
func TestNestedGeneratorHasClusterGenerator_NestedClusterGenerator(t *testing.T) {
nested := argov1alpha1.ApplicationSetNestedGenerator{
Clusters: &argov1alpha1.ClusterGenerator{},

View File

@@ -56,7 +56,7 @@ func TestRequeueAfter(t *testing.T) {
},
}
fakeDynClient := dynfake.NewSimpleDynamicClientWithCustomListKinds(runtime.NewScheme(), gvrToListKind, duckType)
scmConfig := generators.NewSCMConfig("", []string{""}, true, nil, true)
scmConfig := generators.NewSCMConfig("", []string{""}, true, true, nil, true)
terminalGenerators := map[string]generators.Generator{
"List": generators.NewListGenerator(),
"Clusters": generators.NewClusterGenerator(ctx, k8sClient, appClientset, "argocd"),
@@ -129,7 +129,7 @@ func TestRequeueAfter(t *testing.T) {
}},
},
},
}, ""}, want: generators.DefaultRequeueAfterSeconds, wantErr: assert.NoError},
}, ""}, want: generators.DefaultRequeueAfter, wantErr: assert.NoError},
{name: "ClusterMatrixNested", args: args{&argov1alpha1.ApplicationSet{
Spec: argov1alpha1.ApplicationSetSpec{
Generators: []argov1alpha1.ApplicationSetGenerator{
@@ -144,7 +144,7 @@ func TestRequeueAfter(t *testing.T) {
}},
},
},
}, ""}, want: generators.DefaultRequeueAfterSeconds, wantErr: assert.NoError},
}, ""}, want: generators.DefaultRequeueAfter, wantErr: assert.NoError},
{name: "ListGenerator", args: args{appset: &argov1alpha1.ApplicationSet{
Spec: argov1alpha1.ApplicationSetSpec{
Generators: []argov1alpha1.ApplicationSetGenerator{{List: &argov1alpha1.ListGenerator{}}},
@@ -154,7 +154,7 @@ func TestRequeueAfter(t *testing.T) {
Spec: argov1alpha1.ApplicationSetSpec{
Generators: []argov1alpha1.ApplicationSetGenerator{{ClusterDecisionResource: &argov1alpha1.DuckTypeGenerator{}}},
},
}}, want: generators.DefaultRequeueAfterSeconds, wantErr: assert.NoError},
}}, want: generators.DefaultRequeueAfter, wantErr: assert.NoError},
{name: "OverrideRequeueDuck", args: args{
appset: &argov1alpha1.ApplicationSet{
Spec: argov1alpha1.ApplicationSetSpec{

View File

@@ -27,7 +27,7 @@ func Test_ApplyTemplatePatch(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{
Name: "my-cluster-guestbook",
Namespace: "namespace",
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
Finalizers: []string{appv1.ResourcesFinalizerName},
},
Spec: appv1.ApplicationSpec{
Project: "default",
@@ -72,7 +72,7 @@ func Test_ApplyTemplatePatch(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{
Name: "my-cluster-guestbook",
Namespace: "namespace",
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
Finalizers: []string{appv1.ResourcesFinalizerName},
Annotations: map[string]string{
"annotation-some-key": "annotation-some-value",
},
@@ -112,7 +112,7 @@ func Test_ApplyTemplatePatch(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{
Name: "my-cluster-guestbook",
Namespace: "namespace",
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
Finalizers: []string{appv1.ResourcesFinalizerName},
},
Spec: appv1.ApplicationSpec{
Project: "default",
@@ -148,7 +148,7 @@ spec:
ObjectMeta: metav1.ObjectMeta{
Name: "my-cluster-guestbook",
Namespace: "namespace",
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
Finalizers: []string{appv1.ResourcesFinalizerName},
Annotations: map[string]string{
"annotation-some-key": "annotation-some-value",
},

View File

@@ -341,10 +341,10 @@ func TestGenerateAppsUsingPullRequestGenerator(t *testing.T) {
renderer,
nil,
)
assert.EqualValues(t, cases.expectedApp[0].ObjectMeta.Name, gotApp[0].ObjectMeta.Name)
assert.EqualValues(t, cases.expectedApp[0].Spec.Source.TargetRevision, gotApp[0].Spec.Source.TargetRevision)
assert.EqualValues(t, cases.expectedApp[0].Spec.Destination.Namespace, gotApp[0].Spec.Destination.Namespace)
assert.True(t, maps.Equal(cases.expectedApp[0].ObjectMeta.Labels, gotApp[0].ObjectMeta.Labels))
assert.Equal(t, cases.expectedApp[0].Name, gotApp[0].Name)
assert.Equal(t, cases.expectedApp[0].Spec.Source.TargetRevision, gotApp[0].Spec.Source.TargetRevision)
assert.Equal(t, cases.expectedApp[0].Spec.Destination.Namespace, gotApp[0].Spec.Destination.Namespace)
assert.True(t, maps.Equal(cases.expectedApp[0].Labels, gotApp[0].Labels))
})
}
}

View File

@@ -14,7 +14,7 @@ spec:
app: guestbook-ui
spec:
containers:
- image: gcr.io/heptio-images/ks-guestbook-demo:0.2
- image: quay.io/argoprojlabs/argocd-e2e-container:0.2
name: guestbook-ui
ports:
- containerPort: 80

View File

@@ -14,7 +14,7 @@ spec:
app: guestbook-ui
spec:
containers:
- image: gcr.io/heptio-images/ks-guestbook-demo:0.2
- image: quay.io/argoprojlabs/argocd-e2e-container:0.2
name: guestbook-ui
ports:
- containerPort: 80

View File

@@ -5,7 +5,7 @@
replicaCount: 1
image:
repository: gcr.io/heptio-images/ks-guestbook-demo
repository: quay.io/argoprojlabs/argocd-e2e-container
tag: 0.1
pullPolicy: IfNotPresent

View File

@@ -14,7 +14,7 @@ spec:
app: guestbook-ui
spec:
containers:
- image: gcr.io/heptio-images/ks-guestbook-demo:0.2
- image: quay.io/argoprojlabs/argocd-e2e-container:0.2
name: guestbook-ui
ports:
- containerPort: 80

View File

@@ -0,0 +1,26 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
spec:
generators:
- git:
repoURL: https://github.com/argoproj/argo-cd.git
revision: HEAD
files:
- path: "applicationset/examples/git-generator-files-discovery/cluster-config/**/config.json"
- path: "applicationset/examples/git-generator-files-discovery/cluster-config/*/dev/config.json"
exclude: true
template:
metadata:
name: '{{cluster.name}}-guestbook'
spec:
project: default
source:
repoURL: https://github.com/argoproj/argo-cd.git
targetRevision: HEAD
path: "applicationset/examples/git-generator-files-discovery/apps/guestbook"
destination:
server: https://kubernetes.default.svc
#server: '{{cluster.address}}'
namespace: guestbook

View File

@@ -0,0 +1,27 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
spec:
goTemplate: true
goTemplateOptions: ["missingkey=error"]
generators:
- git:
repoURL: https://github.com/argoproj/argo-cd.git
revision: HEAD
files:
- path: "applicationset/examples/git-generator-files-discovery/cluster-config/**/config.json"
- path: "applicationset/examples/git-generator-files-discovery/cluster-config/*/dev/config.json"
exclude: true
template:
metadata:
name: '{{.cluster.name}}-guestbook'
spec:
project: default
source:
repoURL: https://github.com/argoproj/argo-cd.git
targetRevision: HEAD
path: "applicationset/examples/git-generator-files-discovery/apps/guestbook"
destination:
server: https://kubernetes.default.svc
namespace: guestbook

View File

@@ -14,7 +14,7 @@ spec:
app: guestbook-ui
spec:
containers:
- image: gcr.io/heptio-images/ks-guestbook-demo:0.2
- image: quay.io/argoprojlabs/argocd-e2e-container:0.2
name: guestbook-ui
ports:
- containerPort: 80

View File

@@ -14,7 +14,7 @@ spec:
app: guestbook-ui
spec:
containers:
- image: gcr.io/heptio-images/ks-guestbook-demo:0.2
- image: quay.io/argoprojlabs/argocd-e2e-container:0.2
name: guestbook-ui
ports:
- containerPort: 80

View File

@@ -14,7 +14,7 @@ spec:
app: guestbook-ui
spec:
containers:
- image: gcr.io/heptio-images/ks-guestbook-demo:0.2
- image: quay.io/argoprojlabs/argocd-e2e-container:0.2
name: guestbook-ui
ports:
- containerPort: 80

View File

@@ -14,7 +14,7 @@ spec:
app: guestbook-ui
spec:
containers:
- image: gcr.io/heptio-images/ks-guestbook-demo:0.2
- image: quay.io/argoprojlabs/argocd-e2e-container:0.2
name: guestbook-ui
ports:
- containerPort: 80

View File

@@ -7,8 +7,6 @@ import (
log "github.com/sirupsen/logrus"
"github.com/argoproj/argo-cd/v3/util/settings"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
@@ -27,21 +25,17 @@ type ClusterGenerator struct {
ctx context.Context
clientset kubernetes.Interface
// namespace is the Argo CD namespace
namespace string
settingsManager *settings.SettingsManager
namespace string
}
var render = &utils.Render{}
func NewClusterGenerator(ctx context.Context, c client.Client, clientset kubernetes.Interface, namespace string) Generator {
settingsManager := settings.NewSettingsManager(ctx, clientset, namespace)
g := &ClusterGenerator{
Client: c,
ctx: ctx,
clientset: clientset,
namespace: namespace,
settingsManager: settingsManager,
Client: c,
ctx: ctx,
clientset: clientset,
namespace: namespace,
}
return g
}
@@ -59,11 +53,11 @@ func (g *ClusterGenerator) GetTemplate(appSetGenerator *argoappsetv1alpha1.Appli
func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.ApplicationSetGenerator, appSet *argoappsetv1alpha1.ApplicationSet, _ client.Client) ([]map[string]any, error) {
logCtx := log.WithField("applicationset", appSet.GetName()).WithField("namespace", appSet.GetNamespace())
if appSetGenerator == nil {
return nil, EmptyAppSetGeneratorError
return nil, ErrEmptyAppSetGenerator
}
if appSetGenerator.Clusters == nil {
return nil, EmptyAppSetGeneratorError
return nil, ErrEmptyAppSetGenerator
}
// Do not include the local cluster in the cluster parameters IF there is a non-empty selector
@@ -139,20 +133,20 @@ func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.Ap
if appSet.Spec.GoTemplate {
meta := map[string]any{}
if len(cluster.ObjectMeta.Annotations) > 0 {
meta["annotations"] = cluster.ObjectMeta.Annotations
if len(cluster.Annotations) > 0 {
meta["annotations"] = cluster.Annotations
}
if len(cluster.ObjectMeta.Labels) > 0 {
meta["labels"] = cluster.ObjectMeta.Labels
if len(cluster.Labels) > 0 {
meta["labels"] = cluster.Labels
}
params["metadata"] = meta
} else {
for key, value := range cluster.ObjectMeta.Annotations {
for key, value := range cluster.Annotations {
params["metadata.annotations."+key] = value
}
for key, value := range cluster.ObjectMeta.Labels {
for key, value := range cluster.Labels {
params["metadata.labels."+key] = value
}
}
@@ -188,7 +182,7 @@ func (g *ClusterGenerator) getSecretsByClusterName(log *log.Entry, appSetGenerat
return nil, fmt.Errorf("error converting label selector: %w", err)
}
if err := g.Client.List(context.Background(), clusterSecretList, client.MatchingLabelsSelector{Selector: secretSelector}); err != nil {
if err := g.List(context.Background(), clusterSecretList, client.MatchingLabelsSelector{Selector: secretSelector}); err != nil {
return nil, err
}
log.Debugf("clusters matching labels: %d", len(clusterSecretList.Items))

View File

@@ -10,9 +10,8 @@ import (
log "github.com/sirupsen/logrus"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/argoproj/argo-cd/v3/util/settings"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"
@@ -26,22 +25,18 @@ var _ Generator = (*DuckTypeGenerator)(nil)
// DuckTypeGenerator generates Applications for some or all clusters registered with ArgoCD.
type DuckTypeGenerator struct {
ctx context.Context
dynClient dynamic.Interface
clientset kubernetes.Interface
namespace string // namespace is the Argo CD namespace
settingsManager *settings.SettingsManager
ctx context.Context
dynClient dynamic.Interface
clientset kubernetes.Interface
namespace string // namespace is the Argo CD namespace
}
func NewDuckTypeGenerator(ctx context.Context, dynClient dynamic.Interface, clientset kubernetes.Interface, namespace string) Generator {
settingsManager := settings.NewSettingsManager(ctx, clientset, namespace)
g := &DuckTypeGenerator{
ctx: ctx,
dynClient: dynClient,
clientset: clientset,
namespace: namespace,
settingsManager: settingsManager,
ctx: ctx,
dynClient: dynClient,
clientset: clientset,
namespace: namespace,
}
return g
}
@@ -62,12 +57,12 @@ func (g *DuckTypeGenerator) GetTemplate(appSetGenerator *argoprojiov1alpha1.Appl
func (g *DuckTypeGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, appSet *argoprojiov1alpha1.ApplicationSet, _ client.Client) ([]map[string]any, error) {
if appSetGenerator == nil {
return nil, EmptyAppSetGeneratorError
return nil, ErrEmptyAppSetGenerator
}
// Not likely to happen
if appSetGenerator.ClusterDecisionResource == nil {
return nil, EmptyAppSetGeneratorError
return nil, ErrEmptyAppSetGenerator
}
// ListCluster from Argo CD's util/db package will include the local cluster in the list of clusters
@@ -97,13 +92,13 @@ func (g *DuckTypeGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.A
// Validate the fields
if kind == "" || versionIdx < 1 {
log.Warningf("kind=%v, resourceName=%v, versionIdx=%v", kind, resourceName, versionIdx)
return nil, errors.New("There is a problem with the apiVersion, kind or resourceName provided")
return nil, errors.New("there is a problem with the apiVersion, kind or resourceName provided")
}
if (resourceName == "" && labelSelector.MatchLabels == nil && labelSelector.MatchExpressions == nil) ||
(resourceName != "" && (labelSelector.MatchExpressions != nil || labelSelector.MatchLabels != nil)) {
log.Warningf("You must choose either resourceName=%v, labelSelector.matchLabels=%v or labelSelect.matchExpressions=%v", resourceName, labelSelector.MatchLabels, labelSelector.MatchExpressions)
return nil, errors.New("There is a problem with the definition of the ClusterDecisionResource generator")
return nil, errors.New("there is a problem with the definition of the ClusterDecisionResource generator")
}
// Split up the apiVersion
@@ -136,18 +131,51 @@ func (g *DuckTypeGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.A
// Override the duck type in the status of the resource
statusListKey := "clusters"
matchKey := cm.Data["matchKey"]
if cm.Data["statusListKey"] != "" {
statusListKey = cm.Data["statusListKey"]
}
matchKey := cm.Data["matchKey"]
if matchKey == "" {
log.WithField("matchKey", matchKey).Warning("matchKey not found in " + cm.Name)
return nil, nil
}
clusterDecisions := buildClusterDecisions(duckResources, statusListKey)
if len(clusterDecisions) == 0 {
log.Warningf("clusterDecisionResource status.%s missing", statusListKey)
return nil, nil
}
res := []map[string]any{}
for _, clusterDecision := range clusterDecisions {
cluster := findCluster(clustersFromArgoCD, clusterDecision, matchKey, statusListKey)
// if no cluster is found, move to the next cluster
if cluster == nil {
continue
}
// generated instance of cluster params
params := map[string]any{
"name": cluster.Name,
"server": cluster.Server,
}
for key, value := range clusterDecision.(map[string]any) {
params[key] = value.(string)
}
for key, value := range appSetGenerator.ClusterDecisionResource.Values {
collectParams(appSet, params, key, value)
}
res = append(res, params)
}
return res, nil
}
func buildClusterDecisions(duckResources *unstructured.UnstructuredList, statusListKey string) []any {
clusterDecisions := []any{}
// Build the decision slice
@@ -164,60 +192,38 @@ func (g *DuckTypeGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.A
clusterDecisions = append(clusterDecisions, duckResource.Object["status"].(map[string]any)[statusListKey].([]any)...)
}
log.Infof("Number of decisions found: %v", len(clusterDecisions))
if len(clusterDecisions) == 0 {
log.Warningf("clusterDecisionResource status.%s missing", statusListKey)
return nil, nil
}
for _, cluster := range clusterDecisions {
// generated instance of cluster params
params := map[string]any{}
log.Infof("cluster: %v", cluster)
matchValue := cluster.(map[string]any)[matchKey]
if matchValue == nil || matchValue.(string) == "" {
log.Warningf("matchKey=%v not found in \"%v\" list: %v\n", matchKey, statusListKey, cluster.(map[string]any))
continue
}
strMatchValue := matchValue.(string)
log.WithField(matchKey, strMatchValue).Debug("validate against ArgoCD")
found := false
for _, argoCluster := range clustersFromArgoCD {
if argoCluster.Name == strMatchValue {
log.WithField(matchKey, argoCluster.Name).Info("matched cluster in ArgoCD")
params["name"] = argoCluster.Name
params["server"] = argoCluster.Server
found = true
break // Stop looking
}
}
if !found {
log.WithField(matchKey, strMatchValue).Warning("unmatched cluster in ArgoCD")
continue
}
for key, value := range cluster.(map[string]any) {
params[key] = value.(string)
}
for key, value := range appSetGenerator.ClusterDecisionResource.Values {
if appSet.Spec.GoTemplate {
if params["values"] == nil {
params["values"] = map[string]string{}
}
params["values"].(map[string]string)[key] = value
} else {
params["values."+key] = value
}
}
res = append(res, params)
}
return res, nil
return clusterDecisions
}
func findCluster(clustersFromArgoCD []utils.ClusterSpecifier, cluster any, matchKey string, statusListKey string) *utils.ClusterSpecifier {
log.Infof("cluster: %v", cluster)
matchValue := cluster.(map[string]any)[matchKey]
if matchValue == nil || matchValue.(string) == "" {
log.Warningf("matchKey=%v not found in \"%v\" list: %v\n", matchKey, statusListKey, cluster.(map[string]any))
return nil // no match
}
strMatchValue := matchValue.(string)
log.WithField(matchKey, strMatchValue).Debug("validate against ArgoCD")
for _, argoCluster := range clustersFromArgoCD {
if argoCluster.Name == strMatchValue {
log.WithField(matchKey, argoCluster.Name).Info("matched cluster in ArgoCD")
return &argoCluster
}
}
log.WithField(matchKey, strMatchValue).Warning("unmatched cluster in ArgoCD")
return nil
}
func collectParams(appSet *argoprojiov1alpha1.ApplicationSet, params map[string]any, key string, value string) {
if appSet.Spec.GoTemplate {
if params["values"] == nil {
params["values"] = map[string]string{}
}
params["values"].(map[string]string)[key] = value
} else {
params["values."+key] = value
}
}

View File

@@ -159,7 +159,7 @@ func TestGenerateParamsForDuckType(t *testing.T) {
resource: duckType,
values: nil,
expected: []map[string]any{},
expectedError: errors.New("There is a problem with the definition of the ClusterDecisionResource generator"),
expectedError: errors.New("there is a problem with the definition of the ClusterDecisionResource generator"),
},
/*** This does not work with the FAKE runtime client, fieldSelectors are broken.
{
@@ -270,7 +270,7 @@ func TestGenerateParamsForDuckType(t *testing.T) {
resource: duckType,
values: nil,
expected: nil,
expectedError: errors.New("There is a problem with the definition of the ClusterDecisionResource generator"),
expectedError: errors.New("there is a problem with the definition of the ClusterDecisionResource generator"),
},
}
@@ -455,7 +455,7 @@ func TestGenerateParamsForDuckTypeGoTemplate(t *testing.T) {
resource: duckType,
values: nil,
expected: []map[string]any{},
expectedError: errors.New("There is a problem with the definition of the ClusterDecisionResource generator"),
expectedError: errors.New("there is a problem with the definition of the ClusterDecisionResource generator"),
},
/*** This does not work with the FAKE runtime client, fieldSelectors are broken.
{
@@ -566,7 +566,7 @@ func TestGenerateParamsForDuckTypeGoTemplate(t *testing.T) {
resource: duckType,
values: nil,
expected: nil,
expectedError: errors.New("There is a problem with the definition of the ClusterDecisionResource generator"),
expectedError: errors.New("there is a problem with the definition of the ClusterDecisionResource generator"),
},
}

View File

@@ -28,6 +28,7 @@ type GitGenerator struct {
namespace string
}
// NewGitGenerator creates a new instance of Git Generator
func NewGitGenerator(repos services.Repos, namespace string) Generator {
g := &GitGenerator{
repos: repos,
@@ -37,13 +38,17 @@ func NewGitGenerator(repos services.Repos, namespace string) Generator {
return g
}
// GetTemplate returns the ApplicationSetTemplate associated with the Git generator
// from the provided ApplicationSetGenerator. This template defines how each
// generated Argo CD Application should be rendered.
func (g *GitGenerator) GetTemplate(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) *argoprojiov1alpha1.ApplicationSetTemplate {
return &appSetGenerator.Git.Template
}
// GetRequeueAfter returns the duration after which the Git generator should be
// requeued for reconciliation. If RequeueAfterSeconds is set in the generator spec,
// it uses that value. Otherwise, it falls back to a default requeue interval (3 minutes).
func (g *GitGenerator) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) time.Duration {
// Return a requeue default of 3 minutes, if no default is specified.
if appSetGenerator.Git.RequeueAfterSeconds != nil {
return time.Duration(*appSetGenerator.Git.RequeueAfterSeconds) * time.Second
}
@@ -51,13 +56,15 @@ func (g *GitGenerator) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.Appli
return getDefaultRequeueAfter()
}
// GenerateParams generates a list of parameter maps for the ApplicationSet by evaluating the Git generator's configuration.
// It supports both directory-based and file-based Git generators.
func (g *GitGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, appSet *argoprojiov1alpha1.ApplicationSet, client client.Client) ([]map[string]any, error) {
if appSetGenerator == nil {
return nil, EmptyAppSetGeneratorError
return nil, ErrEmptyAppSetGenerator
}
if appSetGenerator.Git == nil {
return nil, EmptyAppSetGeneratorError
return nil, ErrEmptyAppSetGenerator
}
noRevisionCache := appSet.RefreshRequired()
@@ -67,6 +74,7 @@ func (g *GitGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.Applic
// When the project field is templated, the contents of the git repo are required to run the git generator and get the templated value,
// but git generator cannot be called without verifying the commit signature.
// In this case, we skip the signature verification.
// If the project is templated, we skip the commit verification
if !strings.Contains(appSet.Spec.Template.Spec.Project, "{{") {
project := appSet.Spec.Template.Spec.Project
appProject := &argoprojiov1alpha1.AppProject{}
@@ -93,7 +101,7 @@ func (g *GitGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.Applic
case len(appSetGenerator.Git.Files) != 0:
res, err = g.generateParamsForGitFiles(appSetGenerator, noRevisionCache, verifyCommit, appSet.Spec.GoTemplate, project, appSet.Spec.GoTemplateOptions)
default:
return nil, EmptyAppSetGeneratorError
return nil, ErrEmptyAppSetGenerator
}
if err != nil {
return nil, fmt.Errorf("error generating params from git: %w", err)
@@ -102,8 +110,10 @@ func (g *GitGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.Applic
return res, nil
}
// generateParamsForGitDirectories generates parameters for an ApplicationSet using a directory-based Git generator.
// It fetches all directories from the given Git repository and revision, optionally using a revision cache and verifying commits.
// It then filters the directories based on the generator's configuration and renders parameters for the resulting applications
func (g *GitGenerator) generateParamsForGitDirectories(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, noRevisionCache, verifyCommit, useGoTemplate bool, project string, goTemplateOptions []string) ([]map[string]any, error) {
// Directories, not files
allPaths, err := g.repos.GetDirectories(context.TODO(), appSetGenerator.Git.RepoURL, appSetGenerator.Git.Revision, project, noRevisionCache, verifyCommit)
if err != nil {
return nil, fmt.Errorf("error getting directories from repo: %w", err)
@@ -127,41 +137,88 @@ func (g *GitGenerator) generateParamsForGitDirectories(appSetGenerator *argoproj
return res, nil
}
// generateParamsForGitFiles generates parameters for an ApplicationSet using a file-based Git generator.
// It retrieves and processes specified files from the Git repository, supporting both YAML and JSON formats,
// and returns a list of parameter maps extracted from the content.
func (g *GitGenerator) generateParamsForGitFiles(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, noRevisionCache, verifyCommit, useGoTemplate bool, project string, goTemplateOptions []string) ([]map[string]any, error) {
// Get all files that match the requested path string, removing duplicates
allFiles := make(map[string][]byte)
for _, requestedPath := range appSetGenerator.Git.Files {
files, err := g.repos.GetFiles(context.TODO(), appSetGenerator.Git.RepoURL, appSetGenerator.Git.Revision, project, requestedPath.Path, noRevisionCache, verifyCommit)
// fileContentMap maps absolute file paths to their byte content
fileContentMap := make(map[string][]byte)
var includePatterns []string
var excludePatterns []string
for _, req := range appSetGenerator.Git.Files {
if req.Exclude {
excludePatterns = append(excludePatterns, req.Path)
} else {
includePatterns = append(includePatterns, req.Path)
}
}
// Fetch all files from include patterns
for _, includePattern := range includePatterns {
retrievedFiles, err := g.repos.GetFiles(
context.TODO(),
appSetGenerator.Git.RepoURL,
appSetGenerator.Git.Revision,
project,
includePattern,
noRevisionCache,
verifyCommit,
)
if err != nil {
return nil, err
}
for filePath, content := range files {
allFiles[filePath] = content
for absPath, content := range retrievedFiles {
fileContentMap[absPath] = content
}
}
// Extract the unduplicated map into a list, and sort by path to ensure a deterministic
// processing order in the subsequent step
allPaths := []string{}
for path := range allFiles {
allPaths = append(allPaths, path)
}
sort.Strings(allPaths)
// Generate params from each path, and return
res := []map[string]any{}
for _, path := range allPaths {
// A JSON / YAML file path can contain multiple sets of parameters (ie it is an array)
paramsArray, err := g.generateParamsFromGitFile(path, allFiles[path], appSetGenerator.Git.Values, useGoTemplate, goTemplateOptions, appSetGenerator.Git.PathParamPrefix)
// Now remove files matching any exclude pattern
for _, excludePattern := range excludePatterns {
matchingFiles, err := g.repos.GetFiles(
context.TODO(),
appSetGenerator.Git.RepoURL,
appSetGenerator.Git.Revision,
project,
excludePattern,
noRevisionCache,
verifyCommit,
)
if err != nil {
return nil, fmt.Errorf("unable to process file '%s': %w", path, err)
return nil, err
}
for absPath := range matchingFiles {
// if the file doesn't exist already and you try to delete it from the map
// the operation is a no-op. Its safe and doesn't return an error or panic.
// Hence, we can simply try to delete the file from the path without checking
// if that file already exists in the map.
delete(fileContentMap, absPath)
}
res = append(res, paramsArray...)
}
return res, nil
// Get a sorted list of file paths to ensure deterministic processing order
var filePaths []string
for path := range fileContentMap {
filePaths = append(filePaths, path)
}
sort.Strings(filePaths)
var allParams []map[string]any
for _, filePath := range filePaths {
// A JSON / YAML file path can contain multiple sets of parameters (ie it is an array)
paramsFromFileArray, err := g.generateParamsFromGitFile(filePath, fileContentMap[filePath], appSetGenerator.Git.Values, useGoTemplate, goTemplateOptions, appSetGenerator.Git.PathParamPrefix)
if err != nil {
return nil, fmt.Errorf("unable to process file '%s': %w", filePath, err)
}
allParams = append(allParams, paramsFromFileArray...)
}
return allParams, nil
}
// generateParamsFromGitFile parses the content of a Git-tracked file and generates a slice of parameter maps.
// The file can contain a single YAML/JSON object or an array of such objects. Depending on the useGoTemplate flag,
// it either preserves structure for Go templating or flattens the objects for use as plain key-value parameters.
func (g *GitGenerator) generateParamsFromGitFile(filePath string, fileContent []byte, values map[string]string, useGoTemplate bool, goTemplateOptions []string, pathParamPrefix string) ([]map[string]any, error) {
objectsFound := []map[string]any{}
@@ -221,7 +278,7 @@ func (g *GitGenerator) generateParamsFromGitFile(filePath string, fileContent []
params[pathParamName+".basenameNormalized"] = utils.SanitizeName(path.Base(params[pathParamName].(string)))
params[pathParamName+".filenameNormalized"] = utils.SanitizeName(path.Base(params[pathParamName+".filename"].(string)))
for k, v := range strings.Split(params[pathParamName].(string), "/") {
if len(v) > 0 {
if v != "" {
params[pathParamName+"["+strconv.Itoa(k)+"]"] = v
}
}
@@ -238,8 +295,10 @@ func (g *GitGenerator) generateParamsFromGitFile(filePath string, fileContent []
return res, nil
}
// filterApps filters the list of all application paths based on inclusion and exclusion rules
// defined in GitDirectoryGeneratorItems. Each item can either include or exclude matching paths.
func (g *GitGenerator) filterApps(directories []argoprojiov1alpha1.GitDirectoryGeneratorItem, allPaths []string) []string {
res := []string{}
var res []string
for _, appPath := range allPaths {
appInclude := false
appExclude := false
@@ -266,6 +325,9 @@ func (g *GitGenerator) filterApps(directories []argoprojiov1alpha1.GitDirectoryG
return res
}
// generateParamsFromApps generates a list of parameter maps based on the given app paths.
// Each app path is converted into a parameter object with path metadata (basename, segments, etc.).
// It supports both Go templates and flat key-value parameters.
func (g *GitGenerator) generateParamsFromApps(requestedApps []string, appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, useGoTemplate bool, goTemplateOptions []string) ([]map[string]any, error) {
res := make([]map[string]any, len(requestedApps))
for i, a := range requestedApps {
@@ -291,7 +353,7 @@ func (g *GitGenerator) generateParamsFromApps(requestedApps []string, appSetGene
params[pathParamName+".basename"] = path.Base(a)
params[pathParamName+".basenameNormalized"] = utils.SanitizeName(path.Base(a))
for k, v := range strings.Split(params[pathParamName].(string), "/") {
if len(v) > 0 {
if v != "" {
params[pathParamName+"["+strconv.Itoa(k)+"]"] = v
}
}
@@ -308,6 +370,7 @@ func (g *GitGenerator) generateParamsFromApps(requestedApps []string, appSetGene
return res, nil
}
// resolveProjectName resolves a project name whether templated or not
func resolveProjectName(project string) string {
if strings.Contains(project, "{{") {
return ""

View File

@@ -2,7 +2,6 @@ package generators
import (
"errors"
"fmt"
"testing"
"github.com/stretchr/testify/assert"
@@ -181,6 +180,8 @@ foo:
}
func TestGitGenerateParamsFromDirectories(t *testing.T) {
t.Parallel()
cases := []struct {
name string
directories []v1alpha1.GitDirectoryGeneratorItem
@@ -363,6 +364,8 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) {
}
func TestGitGenerateParamsFromDirectoriesGoTemplate(t *testing.T) {
t.Parallel()
cases := []struct {
name string
directories []v1alpha1.GitDirectoryGeneratorItem
@@ -664,6 +667,8 @@ func TestGitGenerateParamsFromDirectoriesGoTemplate(t *testing.T) {
}
func TestGitGenerateParamsFromFiles(t *testing.T) {
t.Parallel()
cases := []struct {
name string
// files is the list of paths/globs to match
@@ -1014,7 +1019,928 @@ cluster:
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appProject).Build()
got, err := gitGenerator.GenerateParams(&applicationSetInfo.Spec.Generators[0], &applicationSetInfo, client)
fmt.Println(got, err)
if testCaseCopy.expectedError != nil {
require.EqualError(t, err, testCaseCopy.expectedError.Error())
} else {
require.NoError(t, err)
assert.ElementsMatch(t, testCaseCopy.expected, got)
}
argoCDServiceMock.AssertExpectations(t)
})
}
}
// TestGitGeneratorParamsFromFilesWithExcludeOptionWithNewGlobbing tests the params values generated by git file generator
// when exclude option is set to true. It gives the result files based on new globbing pattern - doublestar package
func TestGitGeneratorParamsFromFilesWithExcludeOptionWithNewGlobbing(t *testing.T) {
t.Parallel()
cases := []struct {
name string
// files is the list of paths/globs to match
files []v1alpha1.GitFileGeneratorItem
// includePattern contains a list of file patterns that needs to be included
includePattern []string
// excludePattern contains a list of file patterns that needs to be excluded
excludePattern []string
// includeFiles is a map with key as absolute path to file and value as the content in bytes that satisfies the includePattern
includeFiles map[string][]byte
// excludeFiles is a map with key as absolute path to file and value as the content in bytes that satisfies the excludePattern
// This means all the files should be excluded
excludeFiles map[string][]byte
// noMatchFiles contains all the files that neither match include pattern nor exclude pattern
// Instead of keeping those files in the excludeFiles map, it is better to keep those files separately
// in a separate field like 'noMatchFiles' to avoid confusion.
noMatchFiles map[string][]byte
// if repoPathsError is non-nil, the call to GetPaths(...) will return this error value
repoPathsError error
values map[string]string
expected []map[string]any
expectedError error
}{
{
name: "filter files according to file-path with exclude",
files: []v1alpha1.GitFileGeneratorItem{
{
Path: "**/config.json",
},
{
Path: "p1/**/config.json",
Exclude: true,
},
},
includePattern: []string{"**/config.json"},
excludePattern: []string{"p1/**/config.json"},
includeFiles: map[string][]byte{
"cluster-config/production/config.json": []byte(`{
"cluster": {
"owner": "john.doe@example.com",
"name": "production",
"address": "https://kubernetes.default.svc"
},
"key1": "val1",
"key2": {
"key2_1": "val2_1",
"key2_2": {
"key2_2_1": "val2_2_1"
}
},
"key3": 123
}
`),
"p1/config.json": []byte(`{
"database": {
"admin": "db.admin@example.com",
"name": "user-data",
"host": "db.internal.local",
"settings": {
"replicas": 3,
"backup": "daily"
}
}
}
`),
"p1/p2/config.json": []byte(``),
},
excludeFiles: map[string][]byte{
"p1/config.json": []byte(`{
"database": {
"admin": "db.admin@example.com",
"name": "user-data",
"host": "db.internal.local",
"settings": {
"replicas": 3,
"backup": "daily"
}
}
}
`),
"p1/p2/config.json": []byte(``),
},
repoPathsError: nil,
expected: []map[string]any{
{
"cluster.owner": "john.doe@example.com",
"cluster.name": "production",
"cluster.address": "https://kubernetes.default.svc",
"key1": "val1",
"key2.key2_1": "val2_1",
"key2.key2_2.key2_2_1": "val2_2_1",
"key3": "123",
"path": "cluster-config/production",
"path.basename": "production",
"path[0]": "cluster-config",
"path[1]": "production",
"path.basenameNormalized": "production",
"path.filename": "config.json",
"path.filenameNormalized": "config.json",
},
},
},
{
name: "filter files according to multiple file-paths with exclude",
files: []v1alpha1.GitFileGeneratorItem{
{Path: "**/config.json"},
{Path: "p1/app2/config.json", Exclude: true},
{Path: "p1/app3/config.json", Exclude: true},
},
includePattern: []string{"**/config.json"},
excludePattern: []string{"p1/app2/config.json", "p1/app3/config.json"},
includeFiles: map[string][]byte{
"p1/config.json": []byte(`{
"cluster": {
"owner": "john.doe@example.com",
"name": "production",
"address": "https://kubernetes.default.svc",
"inner": {
"one" : "two"
}
}
}`),
"p1/app2/config.json": []byte(`{}`),
"p1/app3/config.json": []byte(`{}`),
},
excludeFiles: map[string][]byte{
"p1/app2/config.json": []byte(`{}`),
"p1/app3/config.json": []byte(`{}`),
},
repoPathsError: nil,
expected: []map[string]any{
{
"cluster.owner": "john.doe@example.com",
"cluster.name": "production",
"cluster.address": "https://kubernetes.default.svc",
"cluster.inner.one": "two",
"path": "p1",
"path.basename": "p1",
"path[0]": "p1",
"path.basenameNormalized": "p1",
"path.filename": "config.json",
"path.filenameNormalized": "config.json",
},
},
},
{
name: "docs example test case to filter files according to multiple file-paths with exclude",
files: []v1alpha1.GitFileGeneratorItem{{Path: "cluster-config/**/config.json"}, {Path: "cluster-config/*/dev/config.json", Exclude: true}},
includePattern: []string{"cluster-config/**/config.json"},
excludePattern: []string{"cluster-config/*/dev/config.json"},
includeFiles: map[string][]byte{
"cluster-config/engineering/prod/config.json": []byte(`
cluster:
owner: john.doe@example.com
name: production
address: https://kubernetes.default.svc
`),
"cluster-config/engineering/dev/config.json": []byte(`
cluster:
owner: foo.bar@example.com
name: staging
address: https://kubernetes.default.svc
`),
},
excludeFiles: map[string][]byte{
"cluster-config/engineering/dev/config.json": []byte(`
cluster:
owner: foo.bar@example.com
name: staging
address: https://kubernetes.default.svc
`),
},
repoPathsError: nil,
expected: []map[string]any{
{
"cluster.owner": "john.doe@example.com",
"cluster.name": "production",
"cluster.address": "https://kubernetes.default.svc",
"path": "cluster-config/engineering/prod",
"path.basename": "prod",
"path[0]": "cluster-config",
"path[1]": "engineering",
"path[2]": "prod",
"path.basenameNormalized": "prod",
"path.filename": "config.json",
"path.filenameNormalized": "config.json",
},
},
},
{
name: "testcase to verify new globbing pattern without any exclude",
files: []v1alpha1.GitFileGeneratorItem{{Path: "some-path/*.yaml"}},
includePattern: []string{"some-path/*.yaml"},
excludePattern: nil,
includeFiles: map[string][]byte{
"some-path/values.yaml": []byte(`
cluster:
owner: john.doe@example.com
name: production
address: https://kubernetes.default.svc
`),
},
excludeFiles: map[string][]byte{},
noMatchFiles: map[string][]byte{
"some-path/staging/values.yaml": []byte(`
cluster:
owner: foo.bar@example.com
name: staging
address: https://kubernetes.default.svc
`),
},
repoPathsError: nil,
expected: []map[string]any{
{
"cluster.owner": "john.doe@example.com",
"cluster.name": "production",
"cluster.address": "https://kubernetes.default.svc",
"path": "some-path",
"path.basename": "some-path",
"path[0]": "some-path",
"path.basenameNormalized": "some-path",
"path.filename": "values.yaml",
"path.filenameNormalized": "values.yaml",
},
},
expectedError: nil,
},
{
name: "test to verify the solution for Git File Generator Problem", // https://github.com/argoproj/argo-cd/blob/master/docs/operator-manual/applicationset/Generators-Git-File-Globbing.md#git-file-generator-globbing
files: []v1alpha1.GitFileGeneratorItem{{Path: "cluster-charts/*/*/values.yaml"}, {Path: "cluster-charts/*/values.yaml", Exclude: true}},
includePattern: []string{"cluster-charts/*/*/values.yaml"},
excludePattern: []string{"cluster-charts/*/values.yaml"},
includeFiles: map[string][]byte{
"cluster-charts/cluster1/mychart/values.yaml": []byte(`
env: staging
`),
"cluster-charts/cluster1/myotherchart/values.yaml": []byte(`
env: prod
`),
},
excludeFiles: map[string][]byte{
"cluster-charts/cluster2/values.yaml": []byte(`
env: dev
`),
},
noMatchFiles: map[string][]byte{
"cluster-charts/cluster1/mychart/charts/mysubchart/values.yaml": []byte(`
env: testing
`),
},
repoPathsError: nil,
expected: []map[string]any{
{
"env": "staging",
"path": "cluster-charts/cluster1/mychart",
"path.filenameNormalized": "values.yaml",
"path[0]": "cluster-charts",
"path[1]": "cluster1",
"path[2]": "mychart",
"path.basename": "mychart",
"path.filename": "values.yaml",
"path.basenameNormalized": "mychart",
},
{
"env": "prod",
"path": "cluster-charts/cluster1/myotherchart",
"path.filenameNormalized": "values.yaml",
"path[0]": "cluster-charts",
"path[1]": "cluster1",
"path[2]": "myotherchart",
"path.basename": "myotherchart",
"path.filename": "values.yaml",
"path.basenameNormalized": "myotherchart",
},
},
expectedError: nil,
},
}
for _, testCase := range cases {
testCaseCopy := testCase
t.Run(testCaseCopy.name, func(t *testing.T) {
t.Parallel()
argoCDServiceMock := mocks.Repos{}
// IMPORTANT: we try to get the files from the repo server that matches the patterns
// If we find those files also satisfy the exclude pattern, we remove them from map
// This is generally done by the g.repos.GetFiles() function.
// With the below mock setup, we make sure that if the GetFiles() function gets called
// for a include or exclude pattern, it should always return the includeFiles or excludeFiles.
for _, pattern := range testCaseCopy.excludePattern {
argoCDServiceMock.
On("GetFiles", mock.Anything, mock.Anything, mock.Anything, mock.Anything, pattern, mock.Anything, mock.Anything).
Return(testCaseCopy.excludeFiles, testCaseCopy.repoPathsError)
}
for _, pattern := range testCaseCopy.includePattern {
argoCDServiceMock.
On("GetFiles", mock.Anything, mock.Anything, mock.Anything, mock.Anything, pattern, mock.Anything, mock.Anything).
Return(testCaseCopy.includeFiles, testCaseCopy.repoPathsError)
}
gitGenerator := NewGitGenerator(&argoCDServiceMock, "")
applicationSetInfo := v1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "set",
},
Spec: v1alpha1.ApplicationSetSpec{
Generators: []v1alpha1.ApplicationSetGenerator{{
Git: &v1alpha1.GitGenerator{
RepoURL: "RepoURL",
Revision: "Revision",
Files: testCaseCopy.files,
Values: testCaseCopy.values,
},
}},
},
}
scheme := runtime.NewScheme()
err := v1alpha1.AddToScheme(scheme)
require.NoError(t, err)
appProject := v1alpha1.AppProject{}
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appProject).Build()
got, err := gitGenerator.GenerateParams(&applicationSetInfo.Spec.Generators[0], &applicationSetInfo, client)
if testCaseCopy.expectedError != nil {
require.EqualError(t, err, testCaseCopy.expectedError.Error())
} else {
require.NoError(t, err)
assert.ElementsMatch(t, testCaseCopy.expected, got)
}
argoCDServiceMock.AssertExpectations(t)
})
}
}
// TestGitGeneratorParamsFromFilesWithExcludeOptionWithOldGlobbing tests the params values generated by git file generator
// // when exclude option is set to true. It gives the result files based on old globbing pattern - git ls-files
func TestGitGeneratorParamsFromFilesWithExcludeOptionWithOldGlobbing(t *testing.T) {
t.Parallel()
cases := []struct {
name string
// files is the list of paths/globs to match
files []v1alpha1.GitFileGeneratorItem
// includePattern contains a list of file patterns that needs to be included
includePattern []string
// excludePattern contains a list of file patterns that needs to be excluded
excludePattern []string
// includeFiles is a map with key as absolute path to file and value as the content in bytes that satisfies the includePattern
includeFiles map[string][]byte
// excludeFiles is a map with key as absolute path to file and value as the content in bytes that satisfies the excludePattern
// This means all the files should be excluded
excludeFiles map[string][]byte
// noMatchFiles contains all the files that neither match include pattern nor exclude pattern
// Instead of keeping those files in the excludeFiles map, it is better to keep those files separately
// in a separate field like 'noMatchFiles' to avoid confusion.
noMatchFiles map[string][]byte
// if repoPathsError is non-nil, the call to GetPaths(...) will return this error value
repoPathsError error
values map[string]string
expected []map[string]any
expectedError error
}{
{
name: "filter files according to file-path with exclude",
files: []v1alpha1.GitFileGeneratorItem{
{
Path: "**/config.json",
},
{
Path: "p1/**/config.json",
Exclude: true,
},
},
includePattern: []string{"**/config.json"},
excludePattern: []string{"p1/**/config.json"},
includeFiles: map[string][]byte{
"cluster-config/production/config.json": []byte(`{
"cluster": {
"owner": "john.doe@example.com",
"name": "production",
"address": "https://kubernetes.default.svc"
},
"key1": "val1",
"key2": {
"key2_1": "val2_1",
"key2_2": {
"key2_2_1": "val2_2_1"
}
},
"key3": 123
}
`),
"p1/config.json": []byte(`{
"database": {
"admin": "db.admin@example.com",
"name": "user-data",
"host": "db.internal.local",
"settings": {
"replicas": 3,
"backup": "daily"
}
}
}
`),
"p1/p2/config.json": []byte(``),
},
excludeFiles: map[string][]byte{
"p1/config.json": []byte(`{
"database": {
"admin": "db.admin@example.com",
"name": "user-data",
"host": "db.internal.local",
"settings": {
"replicas": 3,
"backup": "daily"
}
}
}
`),
"p1/p2/config.json": []byte(``),
},
repoPathsError: nil,
expected: []map[string]any{
{
"cluster.owner": "john.doe@example.com",
"cluster.name": "production",
"cluster.address": "https://kubernetes.default.svc",
"key1": "val1",
"key2.key2_1": "val2_1",
"key2.key2_2.key2_2_1": "val2_2_1",
"key3": "123",
"path": "cluster-config/production",
"path.basename": "production",
"path[0]": "cluster-config",
"path[1]": "production",
"path.basenameNormalized": "production",
"path.filename": "config.json",
"path.filenameNormalized": "config.json",
},
},
},
{
name: "filter files according to multiple file-paths with exclude",
files: []v1alpha1.GitFileGeneratorItem{
{Path: "**/config.json"},
{Path: "p1/app2/config.json", Exclude: true},
{Path: "p1/app3/config.json", Exclude: true},
},
includePattern: []string{"**/config.json"},
excludePattern: []string{"p1/app2/config.json", "p1/app3/config.json"},
includeFiles: map[string][]byte{
"p1/config.json": []byte(`{
"cluster": {
"owner": "john.doe@example.com",
"name": "production",
"address": "https://kubernetes.default.svc",
"inner": {
"one" : "two"
}
}
}`),
"p1/app2/config.json": []byte(`{}`),
"p1/app3/config.json": []byte(`{}`),
},
excludeFiles: map[string][]byte{
"p1/app2/config.json": []byte(`{}`),
"p1/app3/config.json": []byte(`{}`),
},
repoPathsError: nil,
expected: []map[string]any{
{
"cluster.owner": "john.doe@example.com",
"cluster.name": "production",
"cluster.address": "https://kubernetes.default.svc",
"cluster.inner.one": "two",
"path": "p1",
"path.basename": "p1",
"path[0]": "p1",
"path.basenameNormalized": "p1",
"path.filename": "config.json",
"path.filenameNormalized": "config.json",
},
},
},
{
name: "docs example test case to filter files according to multiple file-paths with exclude",
files: []v1alpha1.GitFileGeneratorItem{{Path: "cluster-config/**/config.json"}, {Path: "cluster-config/*/dev/config.json", Exclude: true}},
includePattern: []string{"cluster-config/**/config.json"},
excludePattern: []string{"cluster-config/*/dev/config.json"},
includeFiles: map[string][]byte{
"cluster-config/engineering/prod/config.json": []byte(`
cluster:
owner: john.doe@example.com
name: production
address: https://kubernetes.default.svc
`),
"cluster-config/engineering/dev/config.json": []byte(`
cluster:
owner: foo.bar@example.com
name: staging
address: https://kubernetes.default.svc
`),
},
excludeFiles: map[string][]byte{
"cluster-config/engineering/dev/config.json": []byte(`
cluster:
owner: foo.bar@example.com
name: staging
address: https://kubernetes.default.svc
`),
},
repoPathsError: nil,
expected: []map[string]any{
{
"cluster.owner": "john.doe@example.com",
"cluster.name": "production",
"cluster.address": "https://kubernetes.default.svc",
"path": "cluster-config/engineering/prod",
"path.basename": "prod",
"path[0]": "cluster-config",
"path[1]": "engineering",
"path[2]": "prod",
"path.basenameNormalized": "prod",
"path.filename": "config.json",
"path.filenameNormalized": "config.json",
},
},
},
{
name: "testcase to verify new globbing pattern without any exclude",
files: []v1alpha1.GitFileGeneratorItem{{Path: "some-path/*.yaml"}},
includePattern: []string{"some-path/*.yaml"},
excludePattern: nil,
includeFiles: map[string][]byte{
"some-path/values.yaml": []byte(`
cluster:
owner: john.doe@example.com
name: production
address: https://kubernetes.default.svc
`),
"some-path/staging/values.yaml": []byte(`
cluster:
owner: foo.bar@example.com
name: staging
address: https://kubernetes.default.svc
`),
},
excludeFiles: map[string][]byte{},
repoPathsError: nil,
expected: []map[string]any{
{
"cluster.owner": "john.doe@example.com",
"cluster.name": "production",
"cluster.address": "https://kubernetes.default.svc",
"path": "some-path",
"path.basename": "some-path",
"path[0]": "some-path",
"path.basenameNormalized": "some-path",
"path.filename": "values.yaml",
"path.filenameNormalized": "values.yaml",
},
{
"cluster.owner": "foo.bar@example.com",
"cluster.name": "staging",
"cluster.address": "https://kubernetes.default.svc",
"path": "some-path/staging",
"path.basename": "staging",
"path[0]": "some-path",
"path[1]": "staging",
"path.basenameNormalized": "staging",
"path.filename": "values.yaml",
"path.filenameNormalized": "values.yaml",
},
},
expectedError: nil,
},
{
name: "test to verify the solution for Git File Generator Problem",
files: []v1alpha1.GitFileGeneratorItem{{Path: "cluster-charts/*/*/values.yaml"}, {Path: "cluster-charts/*/values.yaml", Exclude: true}},
includePattern: []string{"cluster-charts/*/*/values.yaml"},
excludePattern: []string{"cluster-charts/*/values.yaml"},
includeFiles: map[string][]byte{
"cluster-charts/cluster1/mychart/values.yaml": []byte(`
env: staging
`),
"cluster-charts/cluster1/myotherchart/values.yaml": []byte(`
env: prod
`),
"cluster-charts/cluster1/mychart/charts/mysubchart/values.yaml": []byte(``),
},
excludeFiles: map[string][]byte{
"cluster-charts/cluster2/values.yaml": []byte(`
env: dev
`),
"cluster-charts/cluster1/mychart/values.yaml": []byte(`
env: staging
`),
"cluster-charts/cluster1/myotherchart/values.yaml": []byte(`
env: prod
`),
"cluster-charts/cluster1/mychart/charts/mysubchart/values.yaml": []byte(``),
},
noMatchFiles: map[string][]byte{
"cluster-charts/cluster1/mychart/charts/mysubchart/values.yaml": []byte(`
env: testing
`),
},
repoPathsError: nil,
expected: []map[string]any{},
expectedError: nil,
},
}
for _, testCase := range cases {
testCaseCopy := testCase
t.Run(testCaseCopy.name, func(t *testing.T) {
t.Parallel()
argoCDServiceMock := mocks.Repos{}
// IMPORTANT: we try to get the files from the repo server that matches the patterns
// If we find those files also satisfy the exclude pattern, we remove them from map
// This is generally done by the g.repos.GetFiles() function.
// With the below mock setup, we make sure that if the GetFiles() function gets called
// for a include or exclude pattern, it should always return the includeFiles or excludeFiles.
for _, pattern := range testCaseCopy.excludePattern {
argoCDServiceMock.
On("GetFiles", mock.Anything, mock.Anything, mock.Anything, mock.Anything, pattern, mock.Anything, mock.Anything).
Return(testCaseCopy.excludeFiles, testCaseCopy.repoPathsError)
}
for _, pattern := range testCaseCopy.includePattern {
argoCDServiceMock.
On("GetFiles", mock.Anything, mock.Anything, mock.Anything, mock.Anything, pattern, mock.Anything, mock.Anything).
Return(testCaseCopy.includeFiles, testCaseCopy.repoPathsError)
}
gitGenerator := NewGitGenerator(&argoCDServiceMock, "")
applicationSetInfo := v1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "set",
},
Spec: v1alpha1.ApplicationSetSpec{
Generators: []v1alpha1.ApplicationSetGenerator{{
Git: &v1alpha1.GitGenerator{
RepoURL: "RepoURL",
Revision: "Revision",
Files: testCaseCopy.files,
Values: testCaseCopy.values,
},
}},
},
}
scheme := runtime.NewScheme()
err := v1alpha1.AddToScheme(scheme)
require.NoError(t, err)
appProject := v1alpha1.AppProject{}
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appProject).Build()
got, err := gitGenerator.GenerateParams(&applicationSetInfo.Spec.Generators[0], &applicationSetInfo, client)
if testCaseCopy.expectedError != nil {
require.EqualError(t, err, testCaseCopy.expectedError.Error())
} else {
require.NoError(t, err)
assert.ElementsMatch(t, testCaseCopy.expected, got)
}
argoCDServiceMock.AssertExpectations(t)
})
}
}
// TestGitGeneratorParamsFromFilesWithExcludeOption tests the params values generated by git file generator
// when exclude option is set to true. It gives the result files based on new globbing pattern - doublestar package
func TestGitGeneratorParamsFromFilesWithExcludeOptionGoTemplate(t *testing.T) {
t.Parallel()
cases := []struct {
name string
// files is the list of paths/globs to match
files []v1alpha1.GitFileGeneratorItem
// includePattern contains a list of file patterns that needs to be included
includePattern []string
// excludePattern contains a list of file patterns that needs to be excluded
excludePattern []string
// includeFiles is a map with key as absolute path to file and value as the content in bytes that satisfies the includePattern
includeFiles map[string][]byte
// excludeFiles is a map with key as absolute path to file and value as the content in bytes that satisfies the excludePattern
// This means all the files should be excluded
excludeFiles map[string][]byte
// if repoPathsError is non-nil, the call to GetPaths(...) will return this error value
repoPathsError error
values map[string]string
expected []map[string]any
expectedError error
}{
{
name: "filter files according to file-path with exclude",
files: []v1alpha1.GitFileGeneratorItem{
{
Path: "**/config.json",
},
{
Path: "p1/**/config.json",
Exclude: true,
},
},
includePattern: []string{"**/config.json"},
excludePattern: []string{"p1/**/config.json"},
includeFiles: map[string][]byte{
"cluster-config/production/config.json": []byte(`{
"cluster": {
"owner": "john.doe@example.com",
"name": "production",
"address": "https://kubernetes.default.svc"
},
"key1": "val1",
"key2": {
"key2_1": "val2_1",
"key2_2": {
"key2_2_1": "val2_2_1"
}
},
"key3": 123
}
`),
},
excludeFiles: map[string][]byte{
"p1/p2/config.json": []byte(`{
"service": {
"maintainer": "dev.team@example.com",
"serviceName": "auth-service",
"endpoint": "http://auth.internal.svc",
"config": {
"retries": 5,
"timeout": "30s"
}
}
}
`),
},
repoPathsError: nil,
expected: []map[string]any{
{
"cluster": map[string]any{
"owner": "john.doe@example.com",
"name": "production",
"address": "https://kubernetes.default.svc",
},
"key1": "val1",
"key2": map[string]any{
"key2_1": "val2_1",
"key2_2": map[string]any{
"key2_2_1": "val2_2_1",
},
},
"key3": float64(123),
"path": map[string]any{
"path": "cluster-config/production",
"basename": "production",
"filename": "config.json",
"basenameNormalized": "production",
"filenameNormalized": "config.json",
"segments": []string{
"cluster-config",
"production",
},
},
},
},
expectedError: nil,
},
{
name: "filter files according to multiple file-paths with exclude",
files: []v1alpha1.GitFileGeneratorItem{
{Path: "**/config.json"},
{Path: "p1/app2/config.json", Exclude: true},
{Path: "p1/app3/config.json", Exclude: true},
},
includePattern: []string{"**/config.json"},
excludePattern: []string{"p1/app2/config.json", "p1/app3/config.json"},
includeFiles: map[string][]byte{
"p1/config.json": []byte(`{
"cluster": {
"owner": "john.doe@example.com",
"name": "production",
"address": "https://kubernetes.default.svc",
"inner": {
"one" : "two"
}
}
}`),
},
excludeFiles: map[string][]byte{
"p1/app2/config.json": []byte(`{
"database": {
"admin": "alice.smith@example.com",
"env": "staging",
"url": "postgres://db.internal.svc:5432",
"settings": {
"replicas": 3,
"backup": "enabled"
}
}
}
`),
"p1/app3/config.json": []byte(`{
"storage": {
"owner": "charlie.brown@example.com",
"bucketName": "app-assets",
"region": "us-west-2",
"options": {
"versioning": true,
"encryption": "AES256"
}
}
}
`),
},
repoPathsError: nil,
expected: []map[string]any{
{
"cluster": map[string]any{
"owner": "john.doe@example.com",
"name": "production",
"address": "https://kubernetes.default.svc",
"inner": map[string]any{
"one": "two",
},
},
"path": map[string]any{
"path": "p1",
"basename": "p1",
"filename": "config.json",
"basenameNormalized": "p1",
"filenameNormalized": "config.json",
"segments": []string{
"p1",
},
},
},
},
expectedError: nil,
},
}
for _, testCase := range cases {
testCaseCopy := testCase
t.Run(testCaseCopy.name, func(t *testing.T) {
t.Parallel()
argoCDServiceMock := mocks.Repos{}
// IMPORTANT: we try to get the files from the repo server that matches the patterns
// If we find those files also satisfy the exclude pattern, we remove them from map
// This is generally done by the g.repos.GetFiles() function.
// With the below mock setup, we make sure that if the GetFiles() function gets called
// for a include or exclude pattern, it should always return the includeFiles or excludeFiles.
for _, pattern := range testCaseCopy.excludePattern {
argoCDServiceMock.
On("GetFiles", mock.Anything, mock.Anything, mock.Anything, mock.Anything, pattern, mock.Anything, mock.Anything).
Return(testCaseCopy.excludeFiles, testCaseCopy.repoPathsError)
}
for _, pattern := range testCaseCopy.includePattern {
argoCDServiceMock.
On("GetFiles", mock.Anything, mock.Anything, mock.Anything, mock.Anything, pattern, mock.Anything, mock.Anything).
Return(testCaseCopy.includeFiles, testCaseCopy.repoPathsError)
}
gitGenerator := NewGitGenerator(&argoCDServiceMock, "")
applicationSetInfo := v1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "set",
},
Spec: v1alpha1.ApplicationSetSpec{
GoTemplate: true,
Generators: []v1alpha1.ApplicationSetGenerator{{
Git: &v1alpha1.GitGenerator{
RepoURL: "RepoURL",
Revision: "Revision",
Files: testCaseCopy.files,
},
}},
},
}
scheme := runtime.NewScheme()
err := v1alpha1.AddToScheme(scheme)
require.NoError(t, err)
appProject := v1alpha1.AppProject{}
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appProject).Build()
got, err := gitGenerator.GenerateParams(&applicationSetInfo.Spec.Generators[0], &applicationSetInfo, client)
if testCaseCopy.expectedError != nil {
require.EqualError(t, err, testCaseCopy.expectedError.Error())
@@ -1029,6 +1955,8 @@ cluster:
}
func TestGitGenerateParamsFromFilesGoTemplate(t *testing.T) {
t.Parallel()
cases := []struct {
name string
// files is the list of paths/globs to match
@@ -1370,7 +2298,6 @@ cluster:
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appProject).Build()
got, err := gitGenerator.GenerateParams(&applicationSetInfo.Spec.Generators[0], &applicationSetInfo, client)
fmt.Println(got, err)
if testCaseCopy.expectedError != nil {
require.EqualError(t, err, testCaseCopy.expectedError.Error())

View File

@@ -27,15 +27,15 @@ type Generator interface {
}
var (
EmptyAppSetGeneratorError = errors.New("ApplicationSet is empty")
NoRequeueAfter time.Duration
ErrEmptyAppSetGenerator = errors.New("ApplicationSet is empty")
NoRequeueAfter time.Duration
)
const (
DefaultRequeueAfterSeconds = 3 * time.Minute
DefaultRequeueAfter = 3 * time.Minute
)
func getDefaultRequeueAfter() time.Duration {
// Default is 3 minutes, min is 1 second, max is 1 year
return env.ParseDurationFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_REQUEUE_AFTER", DefaultRequeueAfterSeconds, 1*time.Second, 8760*time.Hour)
return env.ParseDurationFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_REQUEUE_AFTER", DefaultRequeueAfter, 1*time.Second, 8760*time.Hour)
}

View File

@@ -13,12 +13,12 @@ func Test_getDefaultRequeueAfter(t *testing.T) {
requeueAfterEnv string
want time.Duration
}{
{name: "Default", requeueAfterEnv: "", want: DefaultRequeueAfterSeconds},
{name: "Default", requeueAfterEnv: "", want: DefaultRequeueAfter},
{name: "Min", requeueAfterEnv: "1s", want: 1 * time.Second},
{name: "Max", requeueAfterEnv: "8760h", want: 8760 * time.Hour},
{name: "Override", requeueAfterEnv: "10m", want: 10 * time.Minute},
{name: "LessThanMin", requeueAfterEnv: "1ms", want: DefaultRequeueAfterSeconds},
{name: "MoreThanMax", requeueAfterEnv: "8761h", want: DefaultRequeueAfterSeconds},
{name: "LessThanMin", requeueAfterEnv: "1ms", want: DefaultRequeueAfter},
{name: "MoreThanMax", requeueAfterEnv: "8761h", want: DefaultRequeueAfter},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View File

@@ -31,11 +31,11 @@ func (g *ListGenerator) GetTemplate(appSetGenerator *argoprojiov1alpha1.Applicat
func (g *ListGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, appSet *argoprojiov1alpha1.ApplicationSet, _ client.Client) ([]map[string]any, error) {
if appSetGenerator == nil {
return nil, EmptyAppSetGeneratorError
return nil, ErrEmptyAppSetGenerator
}
if appSetGenerator.List == nil {
return nil, EmptyAppSetGeneratorError
return nil, ErrEmptyAppSetGenerator
}
res := make([]map[string]any, len(appSetGenerator.List.Elements))
@@ -77,7 +77,7 @@ func (g *ListGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.Appli
}
// Append elements from ElementsYaml to the response
if len(appSetGenerator.List.ElementsYaml) > 0 {
if appSetGenerator.List.ElementsYaml != "" {
var yamlElements []map[string]any
err := yaml.Unmarshal([]byte(appSetGenerator.List.ElementsYaml), &yamlElements)
if err != nil {

View File

@@ -34,7 +34,7 @@ func NewMatrixGenerator(supportedGenerators map[string]Generator) Generator {
func (m *MatrixGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, appSet *argoprojiov1alpha1.ApplicationSet, client client.Client) ([]map[string]any, error) {
if appSetGenerator.Matrix == nil {
return nil, EmptyAppSetGeneratorError
return nil, ErrEmptyAppSetGenerator
}
if len(appSetGenerator.Matrix.Generators) < 2 {
@@ -71,7 +71,7 @@ func (m *MatrixGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.App
if err != nil {
return nil, fmt.Errorf("failed to combine string maps with merging params for the matrix generator: %w", err)
}
res = append(res, utils.ConvertToMapStringInterface(val))
res = append(res, val)
}
}
}

View File

@@ -4,12 +4,12 @@ import (
"encoding/json"
"errors"
"fmt"
"maps"
"time"
"dario.cat/mergo"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/argoproj/argo-cd/v3/applicationset/utils"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
)
@@ -52,7 +52,7 @@ func (m *MergeGenerator) getParamSetsForAllGenerators(generators []argoprojiov1a
// GenerateParams gets the params produced by the MergeGenerator.
func (m *MergeGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, appSet *argoprojiov1alpha1.ApplicationSet, client client.Client) ([]map[string]any, error) {
if appSetGenerator.Merge == nil {
return nil, EmptyAppSetGeneratorError
return nil, ErrEmptyAppSetGenerator
}
if len(appSetGenerator.Merge.Generators) < 2 {
@@ -83,11 +83,8 @@ func (m *MergeGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.Appl
}
baseParamSetsByMergeKey[mergeKeyValue] = baseParamSet
} else {
overriddenParamSet, err := utils.CombineStringMapsAllowDuplicates(baseParamSet, overrideParamSet)
if err != nil {
return nil, fmt.Errorf("error combining string maps: %w", err)
}
baseParamSetsByMergeKey[mergeKeyValue] = utils.ConvertToMapStringInterface(overriddenParamSet)
maps.Copy(baseParamSet, overrideParamSet)
baseParamSetsByMergeKey[mergeKeyValue] = baseParamSet
}
}
}

View File

@@ -50,6 +50,8 @@ func listOfMapsToSet(maps []map[string]any) (map[string]bool, error) {
}
func TestMergeGenerate(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
baseGenerators []argoprojiov1alpha1.ApplicationSetNestedGenerator
@@ -210,6 +212,8 @@ func toAPIExtensionsJSON(t *testing.T, g any) *apiextensionsv1.JSON {
}
func TestParamSetsAreUniqueByMergeKeys(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
mergeKeys []string

View File

@@ -1,90 +1,17 @@
// Code generated by mockery v2.52.4. DO NOT EDIT.
// Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package mocks
import (
client "sigs.k8s.io/controller-runtime/pkg/client"
"time"
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
mock "github.com/stretchr/testify/mock"
time "time"
v1alpha1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
// Generator is an autogenerated mock type for the Generator type
type Generator struct {
mock.Mock
}
// GenerateParams provides a mock function with given fields: appSetGenerator, applicationSetInfo, _a2
func (_m *Generator) GenerateParams(appSetGenerator *v1alpha1.ApplicationSetGenerator, applicationSetInfo *v1alpha1.ApplicationSet, _a2 client.Client) ([]map[string]interface{}, error) {
ret := _m.Called(appSetGenerator, applicationSetInfo, _a2)
if len(ret) == 0 {
panic("no return value specified for GenerateParams")
}
var r0 []map[string]interface{}
var r1 error
if rf, ok := ret.Get(0).(func(*v1alpha1.ApplicationSetGenerator, *v1alpha1.ApplicationSet, client.Client) ([]map[string]interface{}, error)); ok {
return rf(appSetGenerator, applicationSetInfo, _a2)
}
if rf, ok := ret.Get(0).(func(*v1alpha1.ApplicationSetGenerator, *v1alpha1.ApplicationSet, client.Client) []map[string]interface{}); ok {
r0 = rf(appSetGenerator, applicationSetInfo, _a2)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]map[string]interface{})
}
}
if rf, ok := ret.Get(1).(func(*v1alpha1.ApplicationSetGenerator, *v1alpha1.ApplicationSet, client.Client) error); ok {
r1 = rf(appSetGenerator, applicationSetInfo, _a2)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetRequeueAfter provides a mock function with given fields: appSetGenerator
func (_m *Generator) GetRequeueAfter(appSetGenerator *v1alpha1.ApplicationSetGenerator) time.Duration {
ret := _m.Called(appSetGenerator)
if len(ret) == 0 {
panic("no return value specified for GetRequeueAfter")
}
var r0 time.Duration
if rf, ok := ret.Get(0).(func(*v1alpha1.ApplicationSetGenerator) time.Duration); ok {
r0 = rf(appSetGenerator)
} else {
r0 = ret.Get(0).(time.Duration)
}
return r0
}
// GetTemplate provides a mock function with given fields: appSetGenerator
func (_m *Generator) GetTemplate(appSetGenerator *v1alpha1.ApplicationSetGenerator) *v1alpha1.ApplicationSetTemplate {
ret := _m.Called(appSetGenerator)
if len(ret) == 0 {
panic("no return value specified for GetTemplate")
}
var r0 *v1alpha1.ApplicationSetTemplate
if rf, ok := ret.Get(0).(func(*v1alpha1.ApplicationSetGenerator) *v1alpha1.ApplicationSetTemplate); ok {
r0 = rf(appSetGenerator)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*v1alpha1.ApplicationSetTemplate)
}
}
return r0
}
// NewGenerator creates a new instance of Generator. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewGenerator(t interface {
@@ -98,3 +25,194 @@ func NewGenerator(t interface {
return mock
}
// Generator is an autogenerated mock type for the Generator type
type Generator struct {
mock.Mock
}
type Generator_Expecter struct {
mock *mock.Mock
}
func (_m *Generator) EXPECT() *Generator_Expecter {
return &Generator_Expecter{mock: &_m.Mock}
}
// GenerateParams provides a mock function for the type Generator
func (_mock *Generator) GenerateParams(appSetGenerator *v1alpha1.ApplicationSetGenerator, applicationSetInfo *v1alpha1.ApplicationSet, client1 client.Client) ([]map[string]any, error) {
ret := _mock.Called(appSetGenerator, applicationSetInfo, client1)
if len(ret) == 0 {
panic("no return value specified for GenerateParams")
}
var r0 []map[string]any
var r1 error
if returnFunc, ok := ret.Get(0).(func(*v1alpha1.ApplicationSetGenerator, *v1alpha1.ApplicationSet, client.Client) ([]map[string]any, error)); ok {
return returnFunc(appSetGenerator, applicationSetInfo, client1)
}
if returnFunc, ok := ret.Get(0).(func(*v1alpha1.ApplicationSetGenerator, *v1alpha1.ApplicationSet, client.Client) []map[string]any); ok {
r0 = returnFunc(appSetGenerator, applicationSetInfo, client1)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]map[string]any)
}
}
if returnFunc, ok := ret.Get(1).(func(*v1alpha1.ApplicationSetGenerator, *v1alpha1.ApplicationSet, client.Client) error); ok {
r1 = returnFunc(appSetGenerator, applicationSetInfo, client1)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Generator_GenerateParams_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GenerateParams'
type Generator_GenerateParams_Call struct {
*mock.Call
}
// GenerateParams is a helper method to define mock.On call
// - appSetGenerator *v1alpha1.ApplicationSetGenerator
// - applicationSetInfo *v1alpha1.ApplicationSet
// - client1 client.Client
func (_e *Generator_Expecter) GenerateParams(appSetGenerator interface{}, applicationSetInfo interface{}, client1 interface{}) *Generator_GenerateParams_Call {
return &Generator_GenerateParams_Call{Call: _e.mock.On("GenerateParams", appSetGenerator, applicationSetInfo, client1)}
}
func (_c *Generator_GenerateParams_Call) Run(run func(appSetGenerator *v1alpha1.ApplicationSetGenerator, applicationSetInfo *v1alpha1.ApplicationSet, client1 client.Client)) *Generator_GenerateParams_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 *v1alpha1.ApplicationSetGenerator
if args[0] != nil {
arg0 = args[0].(*v1alpha1.ApplicationSetGenerator)
}
var arg1 *v1alpha1.ApplicationSet
if args[1] != nil {
arg1 = args[1].(*v1alpha1.ApplicationSet)
}
var arg2 client.Client
if args[2] != nil {
arg2 = args[2].(client.Client)
}
run(
arg0,
arg1,
arg2,
)
})
return _c
}
func (_c *Generator_GenerateParams_Call) Return(stringToVs []map[string]any, err error) *Generator_GenerateParams_Call {
_c.Call.Return(stringToVs, err)
return _c
}
func (_c *Generator_GenerateParams_Call) RunAndReturn(run func(appSetGenerator *v1alpha1.ApplicationSetGenerator, applicationSetInfo *v1alpha1.ApplicationSet, client1 client.Client) ([]map[string]any, error)) *Generator_GenerateParams_Call {
_c.Call.Return(run)
return _c
}
// GetRequeueAfter provides a mock function for the type Generator
func (_mock *Generator) GetRequeueAfter(appSetGenerator *v1alpha1.ApplicationSetGenerator) time.Duration {
ret := _mock.Called(appSetGenerator)
if len(ret) == 0 {
panic("no return value specified for GetRequeueAfter")
}
var r0 time.Duration
if returnFunc, ok := ret.Get(0).(func(*v1alpha1.ApplicationSetGenerator) time.Duration); ok {
r0 = returnFunc(appSetGenerator)
} else {
r0 = ret.Get(0).(time.Duration)
}
return r0
}
// Generator_GetRequeueAfter_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRequeueAfter'
type Generator_GetRequeueAfter_Call struct {
*mock.Call
}
// GetRequeueAfter is a helper method to define mock.On call
// - appSetGenerator *v1alpha1.ApplicationSetGenerator
func (_e *Generator_Expecter) GetRequeueAfter(appSetGenerator interface{}) *Generator_GetRequeueAfter_Call {
return &Generator_GetRequeueAfter_Call{Call: _e.mock.On("GetRequeueAfter", appSetGenerator)}
}
func (_c *Generator_GetRequeueAfter_Call) Run(run func(appSetGenerator *v1alpha1.ApplicationSetGenerator)) *Generator_GetRequeueAfter_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 *v1alpha1.ApplicationSetGenerator
if args[0] != nil {
arg0 = args[0].(*v1alpha1.ApplicationSetGenerator)
}
run(
arg0,
)
})
return _c
}
func (_c *Generator_GetRequeueAfter_Call) Return(duration time.Duration) *Generator_GetRequeueAfter_Call {
_c.Call.Return(duration)
return _c
}
func (_c *Generator_GetRequeueAfter_Call) RunAndReturn(run func(appSetGenerator *v1alpha1.ApplicationSetGenerator) time.Duration) *Generator_GetRequeueAfter_Call {
_c.Call.Return(run)
return _c
}
// GetTemplate provides a mock function for the type Generator
func (_mock *Generator) GetTemplate(appSetGenerator *v1alpha1.ApplicationSetGenerator) *v1alpha1.ApplicationSetTemplate {
ret := _mock.Called(appSetGenerator)
if len(ret) == 0 {
panic("no return value specified for GetTemplate")
}
var r0 *v1alpha1.ApplicationSetTemplate
if returnFunc, ok := ret.Get(0).(func(*v1alpha1.ApplicationSetGenerator) *v1alpha1.ApplicationSetTemplate); ok {
r0 = returnFunc(appSetGenerator)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*v1alpha1.ApplicationSetTemplate)
}
}
return r0
}
// Generator_GetTemplate_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTemplate'
type Generator_GetTemplate_Call struct {
*mock.Call
}
// GetTemplate is a helper method to define mock.On call
// - appSetGenerator *v1alpha1.ApplicationSetGenerator
func (_e *Generator_Expecter) GetTemplate(appSetGenerator interface{}) *Generator_GetTemplate_Call {
return &Generator_GetTemplate_Call{Call: _e.mock.On("GetTemplate", appSetGenerator)}
}
func (_c *Generator_GetTemplate_Call) Run(run func(appSetGenerator *v1alpha1.ApplicationSetGenerator)) *Generator_GetTemplate_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 *v1alpha1.ApplicationSetGenerator
if args[0] != nil {
arg0 = args[0].(*v1alpha1.ApplicationSetGenerator)
}
run(
arg0,
)
})
return _c
}
func (_c *Generator_GetTemplate_Call) Return(applicationSetTemplate *v1alpha1.ApplicationSetTemplate) *Generator_GetTemplate_Call {
_c.Call.Return(applicationSetTemplate)
return _c
}
func (_c *Generator_GetTemplate_Call) RunAndReturn(run func(appSetGenerator *v1alpha1.ApplicationSetGenerator) *v1alpha1.ApplicationSetTemplate) *Generator_GetTemplate_Call {
_c.Call.Return(run)
return _c
}

View File

@@ -10,7 +10,6 @@ import (
"github.com/jeremywohl/flatten"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
"sigs.k8s.io/controller-runtime/pkg/client"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
@@ -20,23 +19,19 @@ import (
)
const (
DefaultPluginRequeueAfterSeconds = 30 * time.Minute
DefaultPluginRequeueAfter = 30 * time.Minute
)
var _ Generator = (*PluginGenerator)(nil)
type PluginGenerator struct {
client client.Client
ctx context.Context
clientset kubernetes.Interface
namespace string
}
func NewPluginGenerator(ctx context.Context, client client.Client, clientset kubernetes.Interface, namespace string) Generator {
func NewPluginGenerator(client client.Client, namespace string) Generator {
g := &PluginGenerator{
client: client,
ctx: ctx,
clientset: clientset,
namespace: namespace,
}
return g
@@ -49,7 +44,7 @@ func (g *PluginGenerator) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.Ap
return time.Duration(*appSetGenerator.Plugin.RequeueAfterSeconds) * time.Second
}
return DefaultPluginRequeueAfterSeconds
return DefaultPluginRequeueAfter
}
func (g *PluginGenerator) GetTemplate(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) *argoprojiov1alpha1.ApplicationSetTemplate {
@@ -58,11 +53,11 @@ func (g *PluginGenerator) GetTemplate(appSetGenerator *argoprojiov1alpha1.Applic
func (g *PluginGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, applicationSetInfo *argoprojiov1alpha1.ApplicationSet, _ client.Client) ([]map[string]any, error) {
if appSetGenerator == nil {
return nil, EmptyAppSetGeneratorError
return nil, ErrEmptyAppSetGenerator
}
if appSetGenerator.Plugin == nil {
return nil, EmptyAppSetGeneratorError
return nil, ErrEmptyAppSetGenerator
}
ctx := context.Background()

View File

@@ -14,8 +14,6 @@ import (
corev1 "k8s.io/api/core/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
kubefake "k8s.io/client-go/kubernetes/fake"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
@@ -628,8 +626,6 @@ func TestPluginGenerateParams(t *testing.T) {
},
}
ctx := t.Context()
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
generatorConfig := argoprojiov1alpha1.ApplicationSetGenerator{
@@ -666,11 +662,9 @@ func TestPluginGenerateParams(t *testing.T) {
testCase.configmap.Data["baseUrl"] = fakeServer.URL
}
fakeClient := kubefake.NewSimpleClientset(append([]runtime.Object{}, testCase.configmap, testCase.secret)...)
fakeClientWithCache := fake.NewClientBuilder().WithObjects([]client.Object{testCase.configmap, testCase.secret}...).Build()
pluginGenerator := NewPluginGenerator(ctx, fakeClientWithCache, fakeClient, "default")
pluginGenerator := NewPluginGenerator(fakeClientWithCache, "default")
applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{

View File

@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"net/http"
"strconv"
"time"
@@ -11,6 +12,7 @@ import (
"github.com/gosimple/slug"
"github.com/argoproj/argo-cd/v3/applicationset/services"
pullrequest "github.com/argoproj/argo-cd/v3/applicationset/services/pull_request"
"github.com/argoproj/argo-cd/v3/applicationset/utils"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
@@ -19,7 +21,7 @@ import (
var _ Generator = (*PullRequestGenerator)(nil)
const (
DefaultPullRequestRequeueAfterSeconds = 30 * time.Minute
DefaultPullRequestRequeueAfter = 30 * time.Minute
)
type PullRequestGenerator struct {
@@ -44,7 +46,7 @@ func (g *PullRequestGenerator) GetRequeueAfter(appSetGenerator *argoprojiov1alph
return time.Duration(*appSetGenerator.PullRequest.RequeueAfterSeconds) * time.Second
}
return DefaultPullRequestRequeueAfterSeconds
return DefaultPullRequestRequeueAfter
}
func (g *PullRequestGenerator) GetTemplate(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) *argoprojiov1alpha1.ApplicationSetTemplate {
@@ -53,11 +55,11 @@ func (g *PullRequestGenerator) GetTemplate(appSetGenerator *argoprojiov1alpha1.A
func (g *PullRequestGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, applicationSetInfo *argoprojiov1alpha1.ApplicationSet, _ client.Client) ([]map[string]any, error) {
if appSetGenerator == nil {
return nil, EmptyAppSetGeneratorError
return nil, ErrEmptyAppSetGenerator
}
if appSetGenerator.PullRequest == nil {
return nil, EmptyAppSetGeneratorError
return nil, ErrEmptyAppSetGenerator
}
ctx := context.Background()
@@ -157,7 +159,8 @@ func (g *PullRequestGenerator) selectServiceProvider(ctx context.Context, genera
if err != nil {
return nil, fmt.Errorf("error fetching Secret token: %w", err)
}
return pullrequest.NewGiteaService(token, providerConfig.API, providerConfig.Owner, providerConfig.Repo, providerConfig.Insecure)
return pullrequest.NewGiteaService(token, providerConfig.API, providerConfig.Owner, providerConfig.Repo, providerConfig.Labels, providerConfig.Insecure)
}
if generatorConfig.BitbucketServer != nil {
providerConfig := generatorConfig.BitbucketServer
@@ -213,12 +216,27 @@ func (g *PullRequestGenerator) selectServiceProvider(ctx context.Context, genera
}
func (g *PullRequestGenerator) github(ctx context.Context, cfg *argoprojiov1alpha1.PullRequestGeneratorGithub, applicationSetInfo *argoprojiov1alpha1.ApplicationSet) (pullrequest.PullRequestService, error) {
var metricsCtx *services.MetricsContext
var httpClient *http.Client
if g.enableGitHubAPIMetrics {
metricsCtx = &services.MetricsContext{
AppSetNamespace: applicationSetInfo.Namespace,
AppSetName: applicationSetInfo.Name,
}
httpClient = services.NewGitHubMetricsClient(metricsCtx)
}
// use an app if it was configured
if cfg.AppSecretName != "" {
auth, err := g.GitHubApps.GetAuthSecret(ctx, cfg.AppSecretName)
if err != nil {
return nil, fmt.Errorf("error getting GitHub App secret: %w", err)
}
if g.enableGitHubAPIMetrics {
return pullrequest.NewGithubAppService(*auth, cfg.API, cfg.Owner, cfg.Repo, cfg.Labels, httpClient)
}
return pullrequest.NewGithubAppService(*auth, cfg.API, cfg.Owner, cfg.Repo, cfg.Labels)
}
@@ -227,5 +245,9 @@ func (g *PullRequestGenerator) github(ctx context.Context, cfg *argoprojiov1alph
if err != nil {
return nil, fmt.Errorf("error fetching Secret token: %w", err)
}
if g.enableGitHubAPIMetrics {
return pullrequest.NewGithubService(token, cfg.API, cfg.Owner, cfg.Repo, cfg.Labels, httpClient)
}
return pullrequest.NewGithubService(token, cfg.API, cfg.Owner, cfg.Repo, cfg.Labels)
}

View File

@@ -275,6 +275,8 @@ func TestPullRequestGithubGenerateParams(t *testing.T) {
}
func TestAllowedSCMProviderPullRequest(t *testing.T) {
t.Parallel()
cases := []struct {
name string
providerConfig *argoprojiov1alpha1.PullRequestGenerator
@@ -325,7 +327,7 @@ func TestAllowedSCMProviderPullRequest(t *testing.T) {
"gitea.myorg.com",
"bitbucket.myorg.com",
"azuredevops.myorg.com",
}, true, nil, true))
}, true, true, nil, true))
applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
@@ -348,7 +350,7 @@ func TestAllowedSCMProviderPullRequest(t *testing.T) {
}
func TestSCMProviderDisabled_PRGenerator(t *testing.T) {
generator := NewPullRequestGenerator(nil, NewSCMConfig("", []string{}, false, nil, true))
generator := NewPullRequestGenerator(nil, NewSCMConfig("", []string{}, false, true, nil, true))
applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{

View File

@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"net/http"
"strings"
"time"
@@ -11,6 +12,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/argoproj/argo-cd/v3/applicationset/services"
"github.com/argoproj/argo-cd/v3/applicationset/services/github_app_auth"
"github.com/argoproj/argo-cd/v3/applicationset/services/scm_provider"
"github.com/argoproj/argo-cd/v3/applicationset/utils"
@@ -21,7 +23,7 @@ import (
var _ Generator = (*SCMProviderGenerator)(nil)
const (
DefaultSCMProviderRequeueAfterSeconds = 30 * time.Minute
DefaultSCMProviderRequeueAfter = 30 * time.Minute
)
type SCMProviderGenerator struct {
@@ -31,20 +33,22 @@ type SCMProviderGenerator struct {
SCMConfig
}
type SCMConfig struct {
scmRootCAPath string
allowedSCMProviders []string
enableSCMProviders bool
GitHubApps github_app_auth.Credentials
tokenRefStrictMode bool
scmRootCAPath string
allowedSCMProviders []string
enableSCMProviders bool
enableGitHubAPIMetrics bool
GitHubApps github_app_auth.Credentials
tokenRefStrictMode bool
}
func NewSCMConfig(scmRootCAPath string, allowedSCMProviders []string, enableSCMProviders bool, gitHubApps github_app_auth.Credentials, tokenRefStrictMode bool) SCMConfig {
func NewSCMConfig(scmRootCAPath string, allowedSCMProviders []string, enableSCMProviders bool, enableGitHubAPIMetrics bool, gitHubApps github_app_auth.Credentials, tokenRefStrictMode bool) SCMConfig {
return SCMConfig{
scmRootCAPath: scmRootCAPath,
allowedSCMProviders: allowedSCMProviders,
enableSCMProviders: enableSCMProviders,
GitHubApps: gitHubApps,
tokenRefStrictMode: tokenRefStrictMode,
scmRootCAPath: scmRootCAPath,
allowedSCMProviders: allowedSCMProviders,
enableSCMProviders: enableSCMProviders,
enableGitHubAPIMetrics: enableGitHubAPIMetrics,
GitHubApps: gitHubApps,
tokenRefStrictMode: tokenRefStrictMode,
}
}
@@ -69,7 +73,7 @@ func (g *SCMProviderGenerator) GetRequeueAfter(appSetGenerator *argoprojiov1alph
return time.Duration(*appSetGenerator.SCMProvider.RequeueAfterSeconds) * time.Second
}
return DefaultSCMProviderRequeueAfterSeconds
return DefaultSCMProviderRequeueAfter
}
func (g *SCMProviderGenerator) GetTemplate(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) *argoprojiov1alpha1.ApplicationSetTemplate {
@@ -118,11 +122,11 @@ func ScmProviderAllowed(applicationSetInfo *argoprojiov1alpha1.ApplicationSet, g
func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, applicationSetInfo *argoprojiov1alpha1.ApplicationSet, _ client.Client) ([]map[string]any, error) {
if appSetGenerator == nil {
return nil, EmptyAppSetGeneratorError
return nil, ErrEmptyAppSetGenerator
}
if appSetGenerator.SCMProvider == nil {
return nil, EmptyAppSetGeneratorError
return nil, ErrEmptyAppSetGenerator
}
if !g.enableSCMProviders {
@@ -253,6 +257,7 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
params := map[string]any{
"organization": repo.Organization,
"repository": repo.Repository,
"repository_id": repo.RepositoryId,
"url": repo.URL,
"branch": repo.Branch,
"sha": repo.SHA,
@@ -273,23 +278,36 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
}
func (g *SCMProviderGenerator) githubProvider(ctx context.Context, github *argoprojiov1alpha1.SCMProviderGeneratorGithub, applicationSetInfo *argoprojiov1alpha1.ApplicationSet) (scm_provider.SCMProviderService, error) {
var metricsCtx *services.MetricsContext
var httpClient *http.Client
if g.enableGitHubAPIMetrics {
metricsCtx = &services.MetricsContext{
AppSetNamespace: applicationSetInfo.Namespace,
AppSetName: applicationSetInfo.Name,
}
httpClient = services.NewGitHubMetricsClient(metricsCtx)
}
if github.AppSecretName != "" {
auth, err := g.GitHubApps.GetAuthSecret(ctx, github.AppSecretName)
if err != nil {
return nil, fmt.Errorf("error fetching Github app secret: %w", err)
}
return scm_provider.NewGithubAppProviderFor(
*auth,
github.Organization,
github.API,
github.AllBranches,
)
if g.enableGitHubAPIMetrics {
return scm_provider.NewGithubAppProviderFor(*auth, github.Organization, github.API, github.AllBranches, httpClient)
}
return scm_provider.NewGithubAppProviderFor(*auth, github.Organization, github.API, github.AllBranches)
}
token, err := utils.GetSecretRef(ctx, g.client, github.TokenRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
if err != nil {
return nil, fmt.Errorf("error fetching Github token: %w", err)
}
if g.enableGitHubAPIMetrics {
return scm_provider.NewGithubProvider(github.Organization, token, github.API, github.AllBranches, httpClient)
}
return scm_provider.NewGithubProvider(github.Organization, token, github.API, github.AllBranches)
}

View File

@@ -12,6 +12,8 @@ import (
)
func TestSCMProviderGenerateParams(t *testing.T) {
t.Parallel()
cases := []struct {
name string
repos []*scm_provider.Repository
@@ -25,6 +27,7 @@ func TestSCMProviderGenerateParams(t *testing.T) {
{
Organization: "myorg",
Repository: "repo1",
RepositoryId: 190320251,
URL: "git@github.com:myorg/repo1.git",
Branch: "main",
SHA: "0bc57212c3cbbec69d20b34c507284bd300def5b",
@@ -33,6 +36,7 @@ func TestSCMProviderGenerateParams(t *testing.T) {
{
Organization: "myorg",
Repository: "repo2",
RepositoryId: 190320252,
URL: "git@github.com:myorg/repo2.git",
Branch: "main",
SHA: "59d0",
@@ -42,6 +46,7 @@ func TestSCMProviderGenerateParams(t *testing.T) {
{
"organization": "myorg",
"repository": "repo1",
"repository_id": 190320251,
"url": "git@github.com:myorg/repo1.git",
"branch": "main",
"branchNormalized": "main",
@@ -53,6 +58,7 @@ func TestSCMProviderGenerateParams(t *testing.T) {
{
"organization": "myorg",
"repository": "repo2",
"repository_id": 190320252,
"url": "git@github.com:myorg/repo2.git",
"branch": "main",
"branchNormalized": "main",
@@ -69,6 +75,7 @@ func TestSCMProviderGenerateParams(t *testing.T) {
{
Organization: "myorg",
Repository: "repo3",
RepositoryId: 190320253,
URL: "git@github.com:myorg/repo3.git",
Branch: "main",
SHA: "0bc57212c3cbbec69d20b34c507284bd300def5b",
@@ -83,6 +90,7 @@ func TestSCMProviderGenerateParams(t *testing.T) {
{
"organization": "myorg",
"repository": "repo3",
"repository_id": 190320253,
"url": "git@github.com:myorg/repo3.git",
"branch": "main",
"branchNormalized": "main",
@@ -95,6 +103,52 @@ func TestSCMProviderGenerateParams(t *testing.T) {
},
},
},
{
name: "Repos with and without id",
repos: []*scm_provider.Repository{
{
Organization: "myorg",
Repository: "repo4",
RepositoryId: "idaz09",
URL: "git@github.com:myorg/repo4.git",
Branch: "main",
SHA: "0bc57212c3cbbec69d20b34c507284bd300def5b",
},
{
Organization: "myorg",
Repository: "repo5",
URL: "git@github.com:myorg/repo5.git",
Branch: "main",
SHA: "0bc57212c3cbbec69d20b34c507284bd300def5b",
},
},
expected: []map[string]any{
{
"organization": "myorg",
"repository": "repo4",
"repository_id": "idaz09",
"url": "git@github.com:myorg/repo4.git",
"branch": "main",
"branchNormalized": "main",
"sha": "0bc57212c3cbbec69d20b34c507284bd300def5b",
"short_sha": "0bc57212",
"short_sha_7": "0bc5721",
"labels": "",
},
{
"organization": "myorg",
"repository": "repo5",
"repository_id": nil,
"url": "git@github.com:myorg/repo5.git",
"branch": "main",
"branchNormalized": "main",
"sha": "0bc57212c3cbbec69d20b34c507284bd300def5b",
"short_sha": "0bc57212",
"short_sha_7": "0bc5721",
"labels": "",
},
},
},
}
for _, testCase := range cases {
@@ -133,6 +187,8 @@ func TestSCMProviderGenerateParams(t *testing.T) {
}
func TestAllowedSCMProvider(t *testing.T) {
t.Parallel()
cases := []struct {
name string
providerConfig *argoprojiov1alpha1.SCMProviderGenerator

View File

@@ -18,7 +18,7 @@ func GetGenerators(ctx context.Context, c client.Client, k8sClient kubernetes.In
"SCMProvider": NewSCMProviderGenerator(c, scmConfig),
"ClusterDecisionResource": NewDuckTypeGenerator(ctx, dynamicClient, k8sClient, namespace),
"PullRequest": NewPullRequestGenerator(c, scmConfig),
"Plugin": NewPluginGenerator(ctx, c, k8sClient, namespace),
"Plugin": NewPluginGenerator(c, namespace),
}
nestedGenerators := map[string]Generator{

View File

@@ -57,7 +57,7 @@ func TestValueInterpolation(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
err := appendTemplatedValues(testCase.values, testCase.params, false, nil)
require.NoError(t, err)
assert.EqualValues(t, testCase.expected, testCase.params)
assert.Equal(t, testCase.expected, testCase.params)
})
}
}
@@ -118,7 +118,7 @@ func TestValueInterpolationWithGoTemplating(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
err := appendTemplatedValues(testCase.values, testCase.params, true, nil)
require.NoError(t, err)
assert.EqualValues(t, testCase.expected, testCase.params)
assert.Equal(t, testCase.expected, testCase.params)
})
}
}

View File

@@ -58,8 +58,7 @@ func NewApplicationsetMetrics(appsetLister applisters.ApplicationSetLister, apps
metrics.Registry.MustRegister(reconcileHistogram)
metrics.Registry.MustRegister(appsetCollector)
kubectlMetricsServer := kubectl.NewKubectlMetrics()
kubectlMetricsServer.RegisterWithClientGo()
kubectl.RegisterWithClientGo()
kubectl.RegisterWithPrometheus(metrics.Registry)
return ApplicationsetMetrics{

View File

@@ -174,7 +174,7 @@ func TestApplicationsetCollector(t *testing.T) {
appsetCollector := newAppsetCollector(utils.NewAppsetLister(client), collectedLabels, filter)
metrics.Registry.MustRegister(appsetCollector)
req, err := http.NewRequest(http.MethodGet, "/metrics", nil)
req, err := http.NewRequest(http.MethodGet, "/metrics", http.NoBody)
require.NoError(t, err)
rr := httptest.NewRecorder()
handler := promhttp.HandlerFor(metrics.Registry, promhttp.HandlerOpts{})
@@ -216,7 +216,7 @@ func TestObserveReconcile(t *testing.T) {
appsetMetrics := NewApplicationsetMetrics(utils.NewAppsetLister(client), collectedLabels, filter)
req, err := http.NewRequest(http.MethodGet, "/metrics", nil)
req, err := http.NewRequest(http.MethodGet, "/metrics", http.NoBody)
require.NoError(t, err)
rr := httptest.NewRecorder()
handler := promhttp.HandlerFor(metrics.Registry, promhttp.HandlerOpts{})

View File

@@ -0,0 +1,241 @@
package services
import (
"net/http"
"strconv"
"time"
"github.com/prometheus/client_golang/prometheus"
log "github.com/sirupsen/logrus"
"sigs.k8s.io/controller-runtime/pkg/metrics"
)
// Doc for the GitHub API rate limit headers:
// https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28#checking-the-status-of-your-rate-limit
// Metric names as constants
const (
githubAPIRequestTotalMetricName = "argocd_github_api_requests_total"
githubAPIRequestDurationMetricName = "argocd_github_api_request_duration_seconds"
githubAPIRateLimitRemainingMetricName = "argocd_github_api_rate_limit_remaining"
githubAPIRateLimitLimitMetricName = "argocd_github_api_rate_limit_limit"
githubAPIRateLimitResetMetricName = "argocd_github_api_rate_limit_reset_seconds"
githubAPIRateLimitUsedMetricName = "argocd_github_api_rate_limit_used"
)
// GitHubMetrics groups all metric vectors for easier injection and registration
type GitHubMetrics struct {
RequestTotal *prometheus.CounterVec
RequestDuration *prometheus.HistogramVec
RateLimitRemaining *prometheus.GaugeVec
RateLimitLimit *prometheus.GaugeVec
RateLimitReset *prometheus.GaugeVec
RateLimitUsed *prometheus.GaugeVec
}
// Factory for a new set of GitHub metrics (for tests or custom registries)
func NewGitHubMetrics() *GitHubMetrics {
return &GitHubMetrics{
RequestTotal: NewGitHubAPIRequestTotal(),
RequestDuration: NewGitHubAPIRequestDuration(),
RateLimitRemaining: NewGitHubAPIRateLimitRemaining(),
RateLimitLimit: NewGitHubAPIRateLimitLimit(),
RateLimitReset: NewGitHubAPIRateLimitReset(),
RateLimitUsed: NewGitHubAPIRateLimitUsed(),
}
}
// Factory functions for each metric vector
func NewGitHubAPIRequestTotal() *prometheus.CounterVec {
return prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: githubAPIRequestTotalMetricName,
Help: "Total number of GitHub API requests",
},
[]string{"method", "endpoint", "status", "appset_namespace", "appset_name"},
)
}
func NewGitHubAPIRequestDuration() *prometheus.HistogramVec {
return prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: githubAPIRequestDurationMetricName,
Help: "GitHub API request duration in seconds",
Buckets: prometheus.DefBuckets,
},
[]string{"method", "endpoint", "appset_namespace", "appset_name"},
)
}
func NewGitHubAPIRateLimitRemaining() *prometheus.GaugeVec {
return prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: githubAPIRateLimitRemainingMetricName,
Help: "The number of requests remaining in the current rate limit window",
},
[]string{"endpoint", "appset_namespace", "appset_name", "resource"},
)
}
func NewGitHubAPIRateLimitLimit() *prometheus.GaugeVec {
return prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: githubAPIRateLimitLimitMetricName,
Help: "The maximum number of requests that you can make per hour",
},
[]string{"endpoint", "appset_namespace", "appset_name", "resource"},
)
}
func NewGitHubAPIRateLimitReset() *prometheus.GaugeVec {
return prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: githubAPIRateLimitResetMetricName,
Help: "The time left till the current rate limit window resets, in seconds",
},
[]string{"endpoint", "appset_namespace", "appset_name", "resource"},
)
}
func NewGitHubAPIRateLimitUsed() *prometheus.GaugeVec {
return prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: githubAPIRateLimitUsedMetricName,
Help: "The number of requests used in the current rate limit window",
},
[]string{"endpoint", "appset_namespace", "appset_name", "resource"},
)
}
// Global metrics (registered with the default registry)
var globalGitHubMetrics = NewGitHubMetrics()
func init() {
log.Debug("Registering GitHub API AppSet metrics")
metrics.Registry.MustRegister(globalGitHubMetrics.RequestTotal)
metrics.Registry.MustRegister(globalGitHubMetrics.RequestDuration)
metrics.Registry.MustRegister(globalGitHubMetrics.RateLimitRemaining)
metrics.Registry.MustRegister(globalGitHubMetrics.RateLimitLimit)
metrics.Registry.MustRegister(globalGitHubMetrics.RateLimitReset)
metrics.Registry.MustRegister(globalGitHubMetrics.RateLimitUsed)
}
type MetricsContext struct {
AppSetNamespace string
AppSetName string
}
// GitHubMetricsTransport is a custom http.RoundTripper that collects GitHub API metrics
type GitHubMetricsTransport struct {
transport http.RoundTripper
metricsContext *MetricsContext
metrics *GitHubMetrics
}
// RoundTrip implements http.RoundTripper interface and collects metrics along with debug logging
func (t *GitHubMetricsTransport) RoundTrip(req *http.Request) (*http.Response, error) {
endpoint := req.URL.Path
method := req.Method
appsetNamespace := "unknown"
appsetName := "unknown"
if t.metricsContext != nil {
appsetNamespace = t.metricsContext.AppSetNamespace
appsetName = t.metricsContext.AppSetName
}
log.WithFields(log.Fields{
"method": method,
"endpoint": endpoint,
"applicationset": map[string]string{"name": appsetName, "namespace": appsetNamespace},
}).Debugf("Invoking GitHub API")
startTime := time.Now()
resp, err := t.transport.RoundTrip(req)
duration := time.Since(startTime)
// Record metrics
t.metrics.RequestDuration.WithLabelValues(method, endpoint, appsetNamespace, appsetName).Observe(duration.Seconds())
status := "0"
if resp != nil {
status = strconv.Itoa(resp.StatusCode)
}
t.metrics.RequestTotal.WithLabelValues(method, endpoint, status, appsetNamespace, appsetName).Inc()
if resp != nil {
resetHumanReadableTime := ""
remainingInt := 0
limitInt := 0
usedInt := 0
resource := resp.Header.Get("X-RateLimit-Resource")
// Record rate limit metrics if available
if resetTime := resp.Header.Get("X-RateLimit-Reset"); resetTime != "" {
if resetUnix, err := strconv.ParseInt(resetTime, 10, 64); err == nil {
// Calculate seconds until reset (reset timestamp - current time)
secondsUntilReset := resetUnix - time.Now().Unix()
t.metrics.RateLimitReset.WithLabelValues(endpoint, appsetNamespace, appsetName, resource).Set(float64(secondsUntilReset))
resetHumanReadableTime = time.Unix(resetUnix, 0).Local().Format("2006-01-02 15:04:05 MST")
}
}
if remaining := resp.Header.Get("X-RateLimit-Remaining"); remaining != "" {
if remainingInt, err = strconv.Atoi(remaining); err == nil {
t.metrics.RateLimitRemaining.WithLabelValues(endpoint, appsetNamespace, appsetName, resource).Set(float64(remainingInt))
}
}
if limit := resp.Header.Get("X-RateLimit-Limit"); limit != "" {
if limitInt, err = strconv.Atoi(limit); err == nil {
t.metrics.RateLimitLimit.WithLabelValues(endpoint, appsetNamespace, appsetName, resource).Set(float64(limitInt))
}
}
if used := resp.Header.Get("X-RateLimit-Used"); used != "" {
if usedInt, err = strconv.Atoi(used); err == nil {
t.metrics.RateLimitUsed.WithLabelValues(endpoint, appsetNamespace, appsetName, resource).Set(float64(usedInt))
}
}
log.WithFields(log.Fields{
"endpoint": endpoint,
"reset": resetHumanReadableTime,
"remaining": remainingInt,
"limit": limitInt,
"used": usedInt,
"resource": resource,
"applicationset": map[string]string{"name": appsetName, "namespace": appsetNamespace},
}).Debugf("GitHub API rate limit info")
}
return resp, err
}
// Full constructor (for tests and advanced use)
func NewGitHubMetricsTransport(
transport http.RoundTripper,
metricsContext *MetricsContext,
metrics *GitHubMetrics,
) *GitHubMetricsTransport {
return &GitHubMetricsTransport{
transport: transport,
metricsContext: metricsContext,
metrics: metrics,
}
}
// Default constructor
func NewDefaultGitHubMetricsTransport(transport http.RoundTripper, metricsContext *MetricsContext) *GitHubMetricsTransport {
return NewGitHubMetricsTransport(
transport,
metricsContext,
globalGitHubMetrics,
)
}
// NewGitHubMetricsClient wraps an http.Client with metrics middleware
func NewGitHubMetricsClient(metricsContext *MetricsContext) *http.Client {
log.Debug("Creating new GitHub metrics client")
return &http.Client{
Transport: NewDefaultGitHubMetricsTransport(http.DefaultTransport, metricsContext),
}
}

View File

@@ -0,0 +1,221 @@
package services
import (
"io"
"net/http"
"net/http/httptest"
"sort"
"strconv"
"strings"
"testing"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/stretchr/testify/assert"
)
type Metric struct {
name string
labels []string
value string
}
var (
endpointLabel = "endpoint=\"/api/test\""
URL = "/api/test"
appsetNamespaceLabel = "appset_namespace=\"test-ns\""
appsetNamespace = "test-ns"
appsetName = "test-appset"
appsetNameLabel = "appset_name=\"test-appset\""
resourceLabel = "resource=\"core\""
rateLimitMetrics = []Metric{
{
name: githubAPIRateLimitRemainingMetricName,
labels: []string{endpointLabel, appsetNamespaceLabel, appsetNameLabel, resourceLabel},
value: "42",
},
{
name: githubAPIRateLimitLimitMetricName,
labels: []string{endpointLabel, appsetNamespaceLabel, appsetNameLabel, resourceLabel},
value: "100",
},
{
name: githubAPIRateLimitUsedMetricName,
labels: []string{endpointLabel, appsetNamespaceLabel, appsetNameLabel, resourceLabel},
value: "58",
},
{
name: githubAPIRateLimitResetMetricName,
labels: []string{endpointLabel, appsetNamespaceLabel, appsetNameLabel, resourceLabel},
value: "1",
},
}
successRequestMetrics = Metric{
name: githubAPIRequestTotalMetricName,
labels: []string{"method=\"GET\"", endpointLabel, "status=\"201\"", appsetNamespaceLabel, appsetNameLabel},
value: "1",
}
failureRequestMetrics = Metric{
name: githubAPIRequestTotalMetricName,
labels: []string{"method=\"GET\"", endpointLabel, "status=\"0\"", appsetNamespaceLabel, appsetNameLabel},
value: "1",
}
)
func TestGitHubMetrics_CollectorApproach_Success(t *testing.T) {
metrics := NewGitHubMetrics()
reg := prometheus.NewRegistry()
reg.MustRegister(
metrics.RequestTotal,
metrics.RequestDuration,
metrics.RateLimitRemaining,
metrics.RateLimitLimit,
metrics.RateLimitReset,
metrics.RateLimitUsed,
)
// Setup a fake HTTP server
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("X-RateLimit-Reset", strconv.FormatInt(time.Now().Unix()+1, 10))
w.Header().Set("X-RateLimit-Remaining", "42")
w.Header().Set("X-RateLimit-Limit", "100")
w.Header().Set("X-RateLimit-Used", "58")
w.Header().Set("X-RateLimit-Resource", "core")
w.WriteHeader(http.StatusCreated)
_, _ = w.Write([]byte("ok"))
}))
defer ts.Close()
metricsCtx := &MetricsContext{AppSetNamespace: appsetNamespace, AppSetName: appsetName}
client := &http.Client{
Transport: NewGitHubMetricsTransport(
http.DefaultTransport,
metricsCtx,
metrics,
),
}
req, _ := http.NewRequest(http.MethodGet, ts.URL+URL, http.NoBody)
resp, err := client.Do(req)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
resp.Body.Close()
// Expose and scrape metrics
handler := promhttp.HandlerFor(reg, promhttp.HandlerOpts{})
server := httptest.NewServer(handler)
defer server.Close()
resp, err = http.Get(server.URL)
if err != nil {
t.Fatalf("failed to scrape metrics: %v", err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
metricsOutput := string(body)
sort.Strings(successRequestMetrics.labels)
assert.Contains(t, metricsOutput, successRequestMetrics.name+"{"+strings.Join(successRequestMetrics.labels, ",")+"} "+successRequestMetrics.value)
for _, metric := range rateLimitMetrics {
sort.Strings(metric.labels)
assert.Contains(t, metricsOutput, metric.name+"{"+strings.Join(metric.labels, ",")+"} "+metric.value)
}
}
type RoundTripperFunc func(*http.Request) (*http.Response, error)
func (f RoundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) }
func TestGitHubMetrics_CollectorApproach_NoRateLimitMetricsOnNilResponse(t *testing.T) {
metrics := NewGitHubMetrics()
reg := prometheus.NewRegistry()
reg.MustRegister(
metrics.RequestTotal,
metrics.RequestDuration,
metrics.RateLimitRemaining,
metrics.RateLimitLimit,
metrics.RateLimitReset,
metrics.RateLimitUsed,
)
client := &http.Client{
Transport: &GitHubMetricsTransport{
transport: RoundTripperFunc(func(*http.Request) (*http.Response, error) {
return nil, http.ErrServerClosed
}),
metricsContext: &MetricsContext{AppSetNamespace: appsetNamespace, AppSetName: appsetName},
metrics: metrics,
},
}
req, _ := http.NewRequest(http.MethodGet, URL, http.NoBody)
_, _ = client.Do(req)
handler := promhttp.HandlerFor(reg, promhttp.HandlerOpts{})
server := httptest.NewServer(handler)
defer server.Close()
resp, err := http.Get(server.URL)
if err != nil {
t.Fatalf("failed to scrape metrics: %v", err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
metricsOutput := string(body)
// Verify request metric exists with status "0"
sort.Strings(failureRequestMetrics.labels)
assert.Contains(t, metricsOutput, failureRequestMetrics.name+"{"+strings.Join(failureRequestMetrics.labels, ",")+"} "+failureRequestMetrics.value)
// Verify rate limit metrics don't exist
for _, metric := range rateLimitMetrics {
sort.Strings(metric.labels)
assert.NotContains(t, metricsOutput, metric.name+"{"+strings.Join(metric.labels, ",")+"} "+metric.value)
}
}
func TestNewGitHubMetricsClient(t *testing.T) {
// Test cases
testCases := []struct {
name string
metricsCtx *MetricsContext
}{
{
name: "with metrics context",
metricsCtx: &MetricsContext{
AppSetNamespace: appsetNamespace,
AppSetName: appsetName,
},
},
{
name: "with nil metrics context",
metricsCtx: nil,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
// Create client
client := NewGitHubMetricsClient(tc.metricsCtx)
// Assert client is not nil
assert.NotNil(t, client)
// Assert transport is properly configured
transport, ok := client.Transport.(*GitHubMetricsTransport)
assert.True(t, ok, "Transport should be GitHubMetricsTransport")
// Verify transport configuration
assert.Equal(t, tc.metricsCtx, transport.metricsContext)
assert.NotNil(t, transport.metrics, "Metrics should not be nil")
assert.Equal(t, http.DefaultTransport, transport.transport, "Base transport should be http.DefaultTransport")
// Verify metrics are global metrics
assert.Equal(t, globalGitHubMetrics, transport.metrics, "Should use global metrics")
})
}
}

View File

@@ -5,14 +5,27 @@ import (
"net/http"
"github.com/bradleyfalzon/ghinstallation/v2"
"github.com/google/go-github/v66/github"
"github.com/google/go-github/v69/github"
"github.com/argoproj/argo-cd/v3/applicationset/services/github_app_auth"
appsetutils "github.com/argoproj/argo-cd/v3/applicationset/utils"
)
func getOptionalHTTPClientAndTransport(optionalHTTPClient ...*http.Client) (*http.Client, http.RoundTripper) {
httpClient := appsetutils.GetOptionalHTTPClient(optionalHTTPClient...)
if len(optionalHTTPClient) > 0 && optionalHTTPClient[0] != nil && optionalHTTPClient[0].Transport != nil {
// will either use the provided custom httpClient and it's transport
return httpClient, optionalHTTPClient[0].Transport
}
// or the default httpClient and transport
return httpClient, http.DefaultTransport
}
// Client builds a github client for the given app authentication.
func Client(g github_app_auth.Authentication, url string) (*github.Client, error) {
rt, err := ghinstallation.New(http.DefaultTransport, g.Id, g.InstallationId, []byte(g.PrivateKey))
func Client(g github_app_auth.Authentication, url string, optionalHTTPClient ...*http.Client) (*github.Client, error) {
httpClient, transport := getOptionalHTTPClientAndTransport(optionalHTTPClient...)
rt, err := ghinstallation.New(transport, g.Id, g.InstallationId, []byte(g.PrivateKey))
if err != nil {
return nil, fmt.Errorf("failed to create github app install: %w", err)
}
@@ -20,13 +33,12 @@ func Client(g github_app_auth.Authentication, url string) (*github.Client, error
url = g.EnterpriseBaseURL
}
var client *github.Client
httpClient.Transport = rt
if url == "" {
httpClient := http.Client{Transport: rt}
client = github.NewClient(&httpClient)
client = github.NewClient(httpClient)
} else {
rt.BaseURL = url
httpClient := http.Client{Transport: rt}
client, err = github.NewClient(&httpClient).WithEnterpriseURLs(url, url)
client, err = github.NewClient(httpClient).WithEnterpriseURLs(url, url)
if err != nil {
return nil, fmt.Errorf("failed to create github enterprise client: %w", err)
}

View File

@@ -91,7 +91,7 @@ func (c *Client) NewRequestWithContext(ctx context.Context, method, path string,
req.Header.Set("Content-Type", "application/json")
}
if len(c.token) != 0 {
if c.token != "" {
req.Header.Set("Authorization", "Bearer "+c.token)
}

View File

@@ -1,78 +1,15 @@
// Code generated by mockery v2.52.4. DO NOT EDIT.
// Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package mocks
import (
context "context"
"context"
mock "github.com/stretchr/testify/mock"
)
// Repos is an autogenerated mock type for the Repos type
type Repos struct {
mock.Mock
}
// GetDirectories provides a mock function with given fields: ctx, repoURL, revision, project, noRevisionCache, verifyCommit
func (_m *Repos) GetDirectories(ctx context.Context, repoURL string, revision string, project string, noRevisionCache bool, verifyCommit bool) ([]string, error) {
ret := _m.Called(ctx, repoURL, revision, project, noRevisionCache, verifyCommit)
if len(ret) == 0 {
panic("no return value specified for GetDirectories")
}
var r0 []string
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, string, string, string, bool, bool) ([]string, error)); ok {
return rf(ctx, repoURL, revision, project, noRevisionCache, verifyCommit)
}
if rf, ok := ret.Get(0).(func(context.Context, string, string, string, bool, bool) []string); ok {
r0 = rf(ctx, repoURL, revision, project, noRevisionCache, verifyCommit)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]string)
}
}
if rf, ok := ret.Get(1).(func(context.Context, string, string, string, bool, bool) error); ok {
r1 = rf(ctx, repoURL, revision, project, noRevisionCache, verifyCommit)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetFiles provides a mock function with given fields: ctx, repoURL, revision, project, pattern, noRevisionCache, verifyCommit
func (_m *Repos) GetFiles(ctx context.Context, repoURL string, revision string, project string, pattern string, noRevisionCache bool, verifyCommit bool) (map[string][]byte, error) {
ret := _m.Called(ctx, repoURL, revision, project, pattern, noRevisionCache, verifyCommit)
if len(ret) == 0 {
panic("no return value specified for GetFiles")
}
var r0 map[string][]byte
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, string, string, string, string, bool, bool) (map[string][]byte, error)); ok {
return rf(ctx, repoURL, revision, project, pattern, noRevisionCache, verifyCommit)
}
if rf, ok := ret.Get(0).(func(context.Context, string, string, string, string, bool, bool) map[string][]byte); ok {
r0 = rf(ctx, repoURL, revision, project, pattern, noRevisionCache, verifyCommit)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(map[string][]byte)
}
}
if rf, ok := ret.Get(1).(func(context.Context, string, string, string, string, bool, bool) error); ok {
r1 = rf(ctx, repoURL, revision, project, pattern, noRevisionCache, verifyCommit)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// NewRepos creates a new instance of Repos. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewRepos(t interface {
@@ -86,3 +23,206 @@ func NewRepos(t interface {
return mock
}
// Repos is an autogenerated mock type for the Repos type
type Repos struct {
mock.Mock
}
type Repos_Expecter struct {
mock *mock.Mock
}
func (_m *Repos) EXPECT() *Repos_Expecter {
return &Repos_Expecter{mock: &_m.Mock}
}
// GetDirectories provides a mock function for the type Repos
func (_mock *Repos) GetDirectories(ctx context.Context, repoURL string, revision string, project string, noRevisionCache bool, verifyCommit bool) ([]string, error) {
ret := _mock.Called(ctx, repoURL, revision, project, noRevisionCache, verifyCommit)
if len(ret) == 0 {
panic("no return value specified for GetDirectories")
}
var r0 []string
var r1 error
if returnFunc, ok := ret.Get(0).(func(context.Context, string, string, string, bool, bool) ([]string, error)); ok {
return returnFunc(ctx, repoURL, revision, project, noRevisionCache, verifyCommit)
}
if returnFunc, ok := ret.Get(0).(func(context.Context, string, string, string, bool, bool) []string); ok {
r0 = returnFunc(ctx, repoURL, revision, project, noRevisionCache, verifyCommit)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]string)
}
}
if returnFunc, ok := ret.Get(1).(func(context.Context, string, string, string, bool, bool) error); ok {
r1 = returnFunc(ctx, repoURL, revision, project, noRevisionCache, verifyCommit)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Repos_GetDirectories_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetDirectories'
type Repos_GetDirectories_Call struct {
*mock.Call
}
// GetDirectories is a helper method to define mock.On call
// - ctx context.Context
// - repoURL string
// - revision string
// - project string
// - noRevisionCache bool
// - verifyCommit bool
func (_e *Repos_Expecter) GetDirectories(ctx interface{}, repoURL interface{}, revision interface{}, project interface{}, noRevisionCache interface{}, verifyCommit interface{}) *Repos_GetDirectories_Call {
return &Repos_GetDirectories_Call{Call: _e.mock.On("GetDirectories", ctx, repoURL, revision, project, noRevisionCache, verifyCommit)}
}
func (_c *Repos_GetDirectories_Call) Run(run func(ctx context.Context, repoURL string, revision string, project string, noRevisionCache bool, verifyCommit bool)) *Repos_GetDirectories_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(context.Context)
}
var arg1 string
if args[1] != nil {
arg1 = args[1].(string)
}
var arg2 string
if args[2] != nil {
arg2 = args[2].(string)
}
var arg3 string
if args[3] != nil {
arg3 = args[3].(string)
}
var arg4 bool
if args[4] != nil {
arg4 = args[4].(bool)
}
var arg5 bool
if args[5] != nil {
arg5 = args[5].(bool)
}
run(
arg0,
arg1,
arg2,
arg3,
arg4,
arg5,
)
})
return _c
}
func (_c *Repos_GetDirectories_Call) Return(strings []string, err error) *Repos_GetDirectories_Call {
_c.Call.Return(strings, err)
return _c
}
func (_c *Repos_GetDirectories_Call) RunAndReturn(run func(ctx context.Context, repoURL string, revision string, project string, noRevisionCache bool, verifyCommit bool) ([]string, error)) *Repos_GetDirectories_Call {
_c.Call.Return(run)
return _c
}
// GetFiles provides a mock function for the type Repos
func (_mock *Repos) GetFiles(ctx context.Context, repoURL string, revision string, project string, pattern string, noRevisionCache bool, verifyCommit bool) (map[string][]byte, error) {
ret := _mock.Called(ctx, repoURL, revision, project, pattern, noRevisionCache, verifyCommit)
if len(ret) == 0 {
panic("no return value specified for GetFiles")
}
var r0 map[string][]byte
var r1 error
if returnFunc, ok := ret.Get(0).(func(context.Context, string, string, string, string, bool, bool) (map[string][]byte, error)); ok {
return returnFunc(ctx, repoURL, revision, project, pattern, noRevisionCache, verifyCommit)
}
if returnFunc, ok := ret.Get(0).(func(context.Context, string, string, string, string, bool, bool) map[string][]byte); ok {
r0 = returnFunc(ctx, repoURL, revision, project, pattern, noRevisionCache, verifyCommit)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(map[string][]byte)
}
}
if returnFunc, ok := ret.Get(1).(func(context.Context, string, string, string, string, bool, bool) error); ok {
r1 = returnFunc(ctx, repoURL, revision, project, pattern, noRevisionCache, verifyCommit)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Repos_GetFiles_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFiles'
type Repos_GetFiles_Call struct {
*mock.Call
}
// GetFiles is a helper method to define mock.On call
// - ctx context.Context
// - repoURL string
// - revision string
// - project string
// - pattern string
// - noRevisionCache bool
// - verifyCommit bool
func (_e *Repos_Expecter) GetFiles(ctx interface{}, repoURL interface{}, revision interface{}, project interface{}, pattern interface{}, noRevisionCache interface{}, verifyCommit interface{}) *Repos_GetFiles_Call {
return &Repos_GetFiles_Call{Call: _e.mock.On("GetFiles", ctx, repoURL, revision, project, pattern, noRevisionCache, verifyCommit)}
}
func (_c *Repos_GetFiles_Call) Run(run func(ctx context.Context, repoURL string, revision string, project string, pattern string, noRevisionCache bool, verifyCommit bool)) *Repos_GetFiles_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(context.Context)
}
var arg1 string
if args[1] != nil {
arg1 = args[1].(string)
}
var arg2 string
if args[2] != nil {
arg2 = args[2].(string)
}
var arg3 string
if args[3] != nil {
arg3 = args[3].(string)
}
var arg4 string
if args[4] != nil {
arg4 = args[4].(string)
}
var arg5 bool
if args[5] != nil {
arg5 = args[5].(bool)
}
var arg6 bool
if args[6] != nil {
arg6 = args[6].(bool)
}
run(
arg0,
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
)
})
return _c
}
func (_c *Repos_GetFiles_Call) Return(stringToBytes map[string][]byte, err error) *Repos_GetFiles_Call {
_c.Call.Return(stringToBytes, err)
return _c
}
func (_c *Repos_GetFiles_Call) RunAndReturn(run func(ctx context.Context, repoURL string, revision string, project string, pattern string, noRevisionCache bool, verifyCommit bool) (map[string][]byte, error)) *Repos_GetFiles_Call {
_c.Call.Return(run)
return _c
}

View File

@@ -5,9 +5,9 @@ import (
"fmt"
"strings"
"github.com/microsoft/azure-devops-go-api/azuredevops"
"github.com/microsoft/azure-devops-go-api/azuredevops/core"
"github.com/microsoft/azure-devops-go-api/azuredevops/git"
"github.com/microsoft/azure-devops-go-api/azuredevops/v7"
"github.com/microsoft/azure-devops-go-api/azuredevops/v7/core"
"github.com/microsoft/azure-devops-go-api/azuredevops/v7/git"
)
const AZURE_DEVOPS_DEFAULT_URL = "https://dev.azure.com"

View File

@@ -4,10 +4,9 @@ import (
"context"
"testing"
"github.com/microsoft/azure-devops-go-api/azuredevops/webapi"
"github.com/microsoft/azure-devops-go-api/azuredevops/core"
"github.com/microsoft/azure-devops-go-api/azuredevops/git"
"github.com/microsoft/azure-devops-go-api/azuredevops/v7/core"
"github.com/microsoft/azure-devops-go-api/azuredevops/v7/git"
"github.com/microsoft/azure-devops-go-api/azuredevops/v7/webapi"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"

View File

@@ -17,10 +17,19 @@ type BitbucketCloudService struct {
}
type BitbucketCloudPullRequest struct {
ID int `json:"id"`
Title string `json:"title"`
Source BitbucketCloudPullRequestSource `json:"source"`
Author BitbucketCloudPullRequestAuthor `json:"author"`
ID int `json:"id"`
Title string `json:"title"`
Source BitbucketCloudPullRequestSource `json:"source"`
Author BitbucketCloudPullRequestAuthor `json:"author"`
Destination BitbucketCloudPullRequestDestination `json:"destination"`
}
type BitbucketCloudPullRequestDestination struct {
Branch BitbucketCloudPullRequestDestinationBranch `json:"branch"`
}
type BitbucketCloudPullRequestDestinationBranch struct {
Name string `json:"name"`
}
type BitbucketCloudPullRequestSource struct {
@@ -136,11 +145,12 @@ func (b *BitbucketCloudService) List(_ context.Context) ([]*PullRequest, error)
pullRequests := []*PullRequest{}
for _, pull := range pulls {
pullRequests = append(pullRequests, &PullRequest{
Number: pull.ID,
Title: pull.Title,
Branch: pull.Source.Branch.Name,
HeadSHA: pull.Source.Commit.Hash,
Author: pull.Author.Nickname,
Number: pull.ID,
Title: pull.Title,
Branch: pull.Source.Branch.Name,
TargetBranch: pull.Destination.Branch.Name,
HeadSHA: pull.Source.Commit.Hash,
Author: pull.Author.Nickname,
})
}

View File

@@ -138,7 +138,7 @@ func TestListPullRequestPaginationCloud(t *testing.T) {
var err error
switch r.RequestURI {
case "/repositories/OWNER/REPO/pullrequests/":
_, err = io.WriteString(w, fmt.Sprintf(`{
_, err = fmt.Fprintf(w, `{
"size": 2,
"pagelen": 1,
"page": 1,
@@ -177,9 +177,9 @@ func TestListPullRequestPaginationCloud(t *testing.T) {
}
}
]
}`, r.Host))
}`, r.Host)
case "/repositories/OWNER/REPO/pullrequests/?pagelen=1&page=2":
_, err = io.WriteString(w, fmt.Sprintf(`{
_, err = fmt.Fprintf(w, `{
"size": 2,
"pagelen": 1,
"page": 2,
@@ -202,7 +202,7 @@ func TestListPullRequestPaginationCloud(t *testing.T) {
}
}
]
}`, r.Host))
}`, r.Host)
default:
t.Fail()
}
@@ -329,7 +329,7 @@ func TestListPullRequestBranchMatchCloud(t *testing.T) {
var err error
switch r.RequestURI {
case "/repositories/OWNER/REPO/pullrequests/":
_, err = io.WriteString(w, fmt.Sprintf(`{
_, err = fmt.Fprintf(w, `{
"size": 2,
"pagelen": 1,
"page": 1,
@@ -349,6 +349,11 @@ func TestListPullRequestBranchMatchCloud(t *testing.T) {
},
"author": {
"nickname": "testName"
},
"destination": {
"branch": {
"name": "master"
}
}
},
{
@@ -365,12 +370,17 @@ func TestListPullRequestBranchMatchCloud(t *testing.T) {
},
"author": {
"nickname": "testName"
},
"destination": {
"branch": {
"name": "branch-200"
}
}
}
]
}`, r.Host))
}`, r.Host)
case "/repositories/OWNER/REPO/pullrequests/?pagelen=1&page=2":
_, err = io.WriteString(w, fmt.Sprintf(`{
_, err = fmt.Fprintf(w, `{
"size": 2,
"pagelen": 1,
"page": 2,
@@ -390,10 +400,15 @@ func TestListPullRequestBranchMatchCloud(t *testing.T) {
},
"author": {
"nickname": "testName"
},
"destination": {
"branch": {
"name": "master"
}
}
}
]
}`, r.Host))
}`, r.Host)
default:
t.Fail()
}
@@ -413,18 +428,20 @@ func TestListPullRequestBranchMatchCloud(t *testing.T) {
require.NoError(t, err)
assert.Len(t, pullRequests, 2)
assert.Equal(t, PullRequest{
Number: 101,
Title: "feat(101)",
Branch: "feature-101",
HeadSHA: "1a8dd249c04a",
Author: "testName",
Number: 101,
Title: "feat(101)",
Branch: "feature-101",
HeadSHA: "1a8dd249c04a",
Author: "testName",
TargetBranch: "master",
}, *pullRequests[0])
assert.Equal(t, PullRequest{
Number: 102,
Title: "feat(102)",
Branch: "feature-102",
HeadSHA: "6344d9623e3b",
Author: "testName",
Number: 102,
Title: "feat(102)",
Branch: "feature-102",
HeadSHA: "6344d9623e3b",
Author: "testName",
TargetBranch: "master",
}, *pullRequests[1])
regexp = `.*2$`
@@ -438,11 +455,12 @@ func TestListPullRequestBranchMatchCloud(t *testing.T) {
require.NoError(t, err)
assert.Len(t, pullRequests, 1)
assert.Equal(t, PullRequest{
Number: 102,
Title: "feat(102)",
Branch: "feature-102",
HeadSHA: "6344d9623e3b",
Author: "testName",
Number: 102,
Title: "feat(102)",
Branch: "feature-102",
HeadSHA: "6344d9623e3b",
Author: "testName",
TargetBranch: "master",
}, *pullRequests[0])
regexp = `[\d{2}`
@@ -454,4 +472,23 @@ func TestListPullRequestBranchMatchCloud(t *testing.T) {
},
})
require.Error(t, err)
regexp = `feature-2[\d]{2}`
targetRegexp := `branch.*`
pullRequests, err = ListPullRequests(t.Context(), svc, []v1alpha1.PullRequestGeneratorFilter{
{
BranchMatch: &regexp,
TargetBranchMatch: &targetRegexp,
},
})
require.NoError(t, err)
assert.Len(t, pullRequests, 1)
assert.Equal(t, PullRequest{
Number: 200,
Title: "feat(200)",
Branch: "feature-200",
HeadSHA: "4cf807e67a6d",
Author: "testName",
TargetBranch: "branch-200",
}, *pullRequests[0])
}

View File

@@ -14,11 +14,12 @@ type GiteaService struct {
client *gitea.Client
owner string
repo string
labels []string
}
var _ PullRequestService = (*GiteaService)(nil)
func NewGiteaService(token, url, owner, repo string, insecure bool) (PullRequestService, error) {
func NewGiteaService(token, url, owner, repo string, labels []string, insecure bool) (PullRequestService, error) {
if token == "" {
token = os.Getenv("GITEA_TOKEN")
}
@@ -42,6 +43,7 @@ func NewGiteaService(token, url, owner, repo string, insecure bool) (PullRequest
client: client,
owner: owner,
repo: repo,
labels: labels,
}, nil
}
@@ -56,6 +58,9 @@ func (g *GiteaService) List(ctx context.Context) ([]*PullRequest, error) {
}
list := []*PullRequest{}
for _, pr := range prs {
if !giteaContainLabels(g.labels, pr.Labels) {
continue
}
list = append(list, &PullRequest{
Number: int(pr.Index),
Title: pr.Title,
@@ -69,6 +74,21 @@ func (g *GiteaService) List(ctx context.Context) ([]*PullRequest, error) {
return list, nil
}
// 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++ {
gotLabelNamesMap[gotLabels[i].Name] = true
}
for _, expected := range expectedLabels {
v, ok := gotLabelNamesMap[expected]
if !v || !ok {
return false
}
}
return true
}
// Get the Gitea pull request label names.
func getGiteaPRLabelNames(giteaLabels []*gitea.Label) []string {
var labelNames []string

View File

@@ -52,7 +52,7 @@ func giteaMockHandler(t *testing.T) func(http.ResponseWriter, *http.Request) {
},
"title": "add an empty file",
"body": "",
"labels": [],
"labels": [{"id": 1, "name": "label1", "color": "00aabb", "description": "foo", "url": ""}],
"milestone": null,
"assignee": null,
"assignees": null,
@@ -246,11 +246,59 @@ func giteaMockHandler(t *testing.T) func(http.ResponseWriter, *http.Request) {
}
}
func TestGiteaContainLabels(t *testing.T) {
cases := []struct {
Name string
Labels []string
PullLabels []*gitea.Label
Expect bool
}{
{
Name: "Match labels",
Labels: []string{"label1", "label2"},
PullLabels: []*gitea.Label{
{Name: "label1"},
{Name: "label2"},
{Name: "label3"},
},
Expect: true,
},
{
Name: "Not match labels",
Labels: []string{"label1", "label4"},
PullLabels: []*gitea.Label{
{Name: "label1"},
{Name: "label2"},
{Name: "label3"},
},
Expect: false,
},
{
Name: "No specify",
Labels: []string{},
PullLabels: []*gitea.Label{
{Name: "label1"},
{Name: "label2"},
{Name: "label3"},
},
Expect: true,
},
}
for _, c := range cases {
t.Run(c.Name, func(t *testing.T) {
if got := giteaContainLabels(c.Labels, c.PullLabels); got != c.Expect {
t.Errorf("expect: %v, got: %v", c.Expect, got)
}
})
}
}
func TestGiteaList(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
giteaMockHandler(t)(w, r)
}))
host, err := NewGiteaService("", ts.URL, "test-argocd", "pr-test", false)
host, err := NewGiteaService("", ts.URL, "test-argocd", "pr-test", []string{"label1"}, false)
require.NoError(t, err)
prs, err := host.List(t.Context())
require.NoError(t, err)

View File

@@ -6,7 +6,9 @@ import (
"net/http"
"os"
"github.com/google/go-github/v66/github"
"github.com/google/go-github/v69/github"
appsetutils "github.com/argoproj/argo-cd/v3/applicationset/utils"
)
type GithubService struct {
@@ -18,15 +20,21 @@ type GithubService struct {
var _ PullRequestService = (*GithubService)(nil)
func NewGithubService(token, url, owner, repo string, labels []string) (PullRequestService, error) {
func NewGithubService(token, url, owner, repo string, labels []string, optionalHTTPClient ...*http.Client) (PullRequestService, error) {
// Undocumented environment variable to set a default token, to be used in testing to dodge anonymous rate limits.
if token == "" {
token = os.Getenv("GITHUB_TOKEN")
}
httpClient := &http.Client{}
var client *github.Client
httpClient := appsetutils.GetOptionalHTTPClient(optionalHTTPClient...)
if url == "" {
client = github.NewClient(httpClient).WithAuthToken(token)
if token == "" {
client = github.NewClient(httpClient)
} else {
client = github.NewClient(httpClient).WithAuthToken(token)
}
} else {
var err error
client, err = github.NewClient(httpClient).WithEnterpriseURLs(url, url)

View File

@@ -1,12 +1,16 @@
package pull_request
import (
"net/http"
"github.com/argoproj/argo-cd/v3/applicationset/services/github_app_auth"
"github.com/argoproj/argo-cd/v3/applicationset/services/internal/github_app"
appsetutils "github.com/argoproj/argo-cd/v3/applicationset/utils"
)
func NewGithubAppService(g github_app_auth.Authentication, url, owner, repo string, labels []string) (PullRequestService, error) {
client, err := github_app.Client(g, url)
func NewGithubAppService(g github_app_auth.Authentication, url, owner, repo string, labels []string, optionalHTTPClient ...*http.Client) (PullRequestService, error) {
httpClient := appsetutils.GetOptionalHTTPClient(optionalHTTPClient...)
client, err := github_app.Client(g, url, httpClient)
if err != nil {
return nil, err
}

View File

@@ -3,7 +3,7 @@ package pull_request
import (
"testing"
"github.com/google/go-github/v66/github"
"github.com/google/go-github/v69/github"
"github.com/stretchr/testify/require"
)

View File

@@ -7,7 +7,7 @@ import (
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v3/reposerver/apiclient"
"github.com/argoproj/argo-cd/v3/util/db"
"github.com/argoproj/argo-cd/v3/util/io"
utilio "github.com/argoproj/argo-cd/v3/util/io"
)
type argoCDService struct {
@@ -36,7 +36,7 @@ func NewArgoCDService(db db.ArgoDB, submoduleEnabled bool, repoClientset apiclie
if err != nil {
return nil, fmt.Errorf("error initializing new repo server client: %w", err)
}
defer io.Close(closer)
defer utilio.Close(closer)
return client.GetGitFiles(ctx, fileRequest)
},
getGitDirectoriesFromRepoServer: func(ctx context.Context, dirRequest *apiclient.GitDirectoriesRequest) (*apiclient.GitDirectoriesResponse, error) {
@@ -44,7 +44,7 @@ func NewArgoCDService(db db.ArgoDB, submoduleEnabled bool, repoClientset apiclie
if err != nil {
return nil, fmt.Errorf("error initialising new repo server client: %w", err)
}
defer io.Close(closer)
defer utilio.Close(closer)
return client.GetGitDirectories(ctx, dirRequest)
},
}

View File

@@ -4,22 +4,21 @@ import (
"context"
"errors"
"fmt"
"maps"
pathpkg "path"
"path/filepath"
"slices"
"strings"
"github.com/aws/aws-sdk-go/aws/request"
"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"
log "github.com/sirupsen/logrus"
"golang.org/x/exp/maps"
"k8s.io/utils/strings/slices"
application "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
)
@@ -299,7 +298,7 @@ func (p *AWSCodeCommitProvider) getTagFilters() []*resourcegroupstaggingapi.TagF
filter.Values = append(filter.Values, aws.String(tagFilter.Value))
}
}
return maps.Values(filters)
return slices.Collect(maps.Values(filters))
}
func getCodeCommitRepoName(repoArn string) (string, error) {
@@ -341,7 +340,7 @@ func toAbsolutePath(path string) string {
if filepath.IsAbs(path) {
return path
}
return filepath.ToSlash(filepath.Join("/", path))
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) {

View File

@@ -1,170 +1,16 @@
// Code generated by mockery v2.52.4. DO NOT EDIT.
// Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package mocks
import (
context "context"
codecommit "github.com/aws/aws-sdk-go/service/codecommit"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/service/codecommit"
mock "github.com/stretchr/testify/mock"
request "github.com/aws/aws-sdk-go/aws/request"
)
// AWSCodeCommitClient is an autogenerated mock type for the AWSCodeCommitClient type
type AWSCodeCommitClient struct {
mock.Mock
}
// GetFolderWithContext provides a mock function with given fields: _a0, _a1, _a2
func (_m *AWSCodeCommitClient) GetFolderWithContext(_a0 context.Context, _a1 *codecommit.GetFolderInput, _a2 ...request.Option) (*codecommit.GetFolderOutput, error) {
_va := make([]interface{}, len(_a2))
for _i := range _a2 {
_va[_i] = _a2[_i]
}
var _ca []interface{}
_ca = append(_ca, _a0, _a1)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for GetFolderWithContext")
}
var r0 *codecommit.GetFolderOutput
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *codecommit.GetFolderInput, ...request.Option) (*codecommit.GetFolderOutput, error)); ok {
return rf(_a0, _a1, _a2...)
}
if rf, ok := ret.Get(0).(func(context.Context, *codecommit.GetFolderInput, ...request.Option) *codecommit.GetFolderOutput); ok {
r0 = rf(_a0, _a1, _a2...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*codecommit.GetFolderOutput)
}
}
if rf, ok := ret.Get(1).(func(context.Context, *codecommit.GetFolderInput, ...request.Option) error); ok {
r1 = rf(_a0, _a1, _a2...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetRepositoryWithContext provides a mock function with given fields: _a0, _a1, _a2
func (_m *AWSCodeCommitClient) GetRepositoryWithContext(_a0 context.Context, _a1 *codecommit.GetRepositoryInput, _a2 ...request.Option) (*codecommit.GetRepositoryOutput, error) {
_va := make([]interface{}, len(_a2))
for _i := range _a2 {
_va[_i] = _a2[_i]
}
var _ca []interface{}
_ca = append(_ca, _a0, _a1)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for GetRepositoryWithContext")
}
var r0 *codecommit.GetRepositoryOutput
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *codecommit.GetRepositoryInput, ...request.Option) (*codecommit.GetRepositoryOutput, error)); ok {
return rf(_a0, _a1, _a2...)
}
if rf, ok := ret.Get(0).(func(context.Context, *codecommit.GetRepositoryInput, ...request.Option) *codecommit.GetRepositoryOutput); ok {
r0 = rf(_a0, _a1, _a2...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*codecommit.GetRepositoryOutput)
}
}
if rf, ok := ret.Get(1).(func(context.Context, *codecommit.GetRepositoryInput, ...request.Option) error); ok {
r1 = rf(_a0, _a1, _a2...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// ListBranchesWithContext provides a mock function with given fields: _a0, _a1, _a2
func (_m *AWSCodeCommitClient) ListBranchesWithContext(_a0 context.Context, _a1 *codecommit.ListBranchesInput, _a2 ...request.Option) (*codecommit.ListBranchesOutput, error) {
_va := make([]interface{}, len(_a2))
for _i := range _a2 {
_va[_i] = _a2[_i]
}
var _ca []interface{}
_ca = append(_ca, _a0, _a1)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for ListBranchesWithContext")
}
var r0 *codecommit.ListBranchesOutput
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *codecommit.ListBranchesInput, ...request.Option) (*codecommit.ListBranchesOutput, error)); ok {
return rf(_a0, _a1, _a2...)
}
if rf, ok := ret.Get(0).(func(context.Context, *codecommit.ListBranchesInput, ...request.Option) *codecommit.ListBranchesOutput); ok {
r0 = rf(_a0, _a1, _a2...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*codecommit.ListBranchesOutput)
}
}
if rf, ok := ret.Get(1).(func(context.Context, *codecommit.ListBranchesInput, ...request.Option) error); ok {
r1 = rf(_a0, _a1, _a2...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// ListRepositoriesWithContext provides a mock function with given fields: _a0, _a1, _a2
func (_m *AWSCodeCommitClient) ListRepositoriesWithContext(_a0 context.Context, _a1 *codecommit.ListRepositoriesInput, _a2 ...request.Option) (*codecommit.ListRepositoriesOutput, error) {
_va := make([]interface{}, len(_a2))
for _i := range _a2 {
_va[_i] = _a2[_i]
}
var _ca []interface{}
_ca = append(_ca, _a0, _a1)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for ListRepositoriesWithContext")
}
var r0 *codecommit.ListRepositoriesOutput
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *codecommit.ListRepositoriesInput, ...request.Option) (*codecommit.ListRepositoriesOutput, error)); ok {
return rf(_a0, _a1, _a2...)
}
if rf, ok := ret.Get(0).(func(context.Context, *codecommit.ListRepositoriesInput, ...request.Option) *codecommit.ListRepositoriesOutput); ok {
r0 = rf(_a0, _a1, _a2...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*codecommit.ListRepositoriesOutput)
}
}
if rf, ok := ret.Get(1).(func(context.Context, *codecommit.ListRepositoriesInput, ...request.Option) error); ok {
r1 = rf(_a0, _a1, _a2...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// NewAWSCodeCommitClient creates a new instance of AWSCodeCommitClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewAWSCodeCommitClient(t interface {
@@ -178,3 +24,364 @@ func NewAWSCodeCommitClient(t interface {
return mock
}
// AWSCodeCommitClient is an autogenerated mock type for the AWSCodeCommitClient type
type AWSCodeCommitClient struct {
mock.Mock
}
type AWSCodeCommitClient_Expecter struct {
mock *mock.Mock
}
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]
}
var _ca []interface{}
_ca = append(_ca, v, getFolderInput)
_ca = append(_ca, _va...)
ret := _mock.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for GetFolderWithContext")
}
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(aws.Context, *codecommit.GetFolderInput, ...request.Option) *codecommit.GetFolderOutput); ok {
r0 = returnFunc(v, getFolderInput, options...)
} 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...)
} 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 {
*mock.Call
}
// GetFolderWithContext is a helper method to define mock.On call
// - v aws.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...)...)}
}
func (_c *AWSCodeCommitClient_GetFolderWithContext_Call) Run(run func(v aws.Context, getFolderInput *codecommit.GetFolderInput, options ...request.Option)) *AWSCodeCommitClient_GetFolderWithContext_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 aws.Context
if args[0] != nil {
arg0 = args[0].(aws.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)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(request.Option)
}
}
arg2 = variadicArgs
run(
arg0,
arg1,
arg2...,
)
})
return _c
}
func (_c *AWSCodeCommitClient_GetFolderWithContext_Call) Return(getFolderOutput *codecommit.GetFolderOutput, err error) *AWSCodeCommitClient_GetFolderWithContext_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 {
_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]
}
var _ca []interface{}
_ca = append(_ca, v, getRepositoryInput)
_ca = append(_ca, _va...)
ret := _mock.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for GetRepositoryWithContext")
}
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(aws.Context, *codecommit.GetRepositoryInput, ...request.Option) *codecommit.GetRepositoryOutput); ok {
r0 = returnFunc(v, getRepositoryInput, options...)
} 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...)
} 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 {
*mock.Call
}
// GetRepositoryWithContext is a helper method to define mock.On call
// - v aws.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...)...)}
}
func (_c *AWSCodeCommitClient_GetRepositoryWithContext_Call) Run(run func(v aws.Context, getRepositoryInput *codecommit.GetRepositoryInput, options ...request.Option)) *AWSCodeCommitClient_GetRepositoryWithContext_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 aws.Context
if args[0] != nil {
arg0 = args[0].(aws.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)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(request.Option)
}
}
arg2 = variadicArgs
run(
arg0,
arg1,
arg2...,
)
})
return _c
}
func (_c *AWSCodeCommitClient_GetRepositoryWithContext_Call) Return(getRepositoryOutput *codecommit.GetRepositoryOutput, err error) *AWSCodeCommitClient_GetRepositoryWithContext_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 {
_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]
}
var _ca []interface{}
_ca = append(_ca, v, listBranchesInput)
_ca = append(_ca, _va...)
ret := _mock.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for ListBranchesWithContext")
}
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(aws.Context, *codecommit.ListBranchesInput, ...request.Option) *codecommit.ListBranchesOutput); ok {
r0 = returnFunc(v, listBranchesInput, options...)
} 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...)
} 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 {
*mock.Call
}
// ListBranchesWithContext is a helper method to define mock.On call
// - v aws.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...)...)}
}
func (_c *AWSCodeCommitClient_ListBranchesWithContext_Call) Run(run func(v aws.Context, listBranchesInput *codecommit.ListBranchesInput, options ...request.Option)) *AWSCodeCommitClient_ListBranchesWithContext_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 aws.Context
if args[0] != nil {
arg0 = args[0].(aws.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)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(request.Option)
}
}
arg2 = variadicArgs
run(
arg0,
arg1,
arg2...,
)
})
return _c
}
func (_c *AWSCodeCommitClient_ListBranchesWithContext_Call) Return(listBranchesOutput *codecommit.ListBranchesOutput, err error) *AWSCodeCommitClient_ListBranchesWithContext_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 {
_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]
}
var _ca []interface{}
_ca = append(_ca, v, listRepositoriesInput)
_ca = append(_ca, _va...)
ret := _mock.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for ListRepositoriesWithContext")
}
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(aws.Context, *codecommit.ListRepositoriesInput, ...request.Option) *codecommit.ListRepositoriesOutput); ok {
r0 = returnFunc(v, listRepositoriesInput, options...)
} 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...)
} 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 {
*mock.Call
}
// ListRepositoriesWithContext is a helper method to define mock.On call
// - v aws.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...)...)}
}
func (_c *AWSCodeCommitClient_ListRepositoriesWithContext_Call) Run(run func(v aws.Context, listRepositoriesInput *codecommit.ListRepositoriesInput, options ...request.Option)) *AWSCodeCommitClient_ListRepositoriesWithContext_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 aws.Context
if args[0] != nil {
arg0 = args[0].(aws.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)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(request.Option)
}
}
arg2 = variadicArgs
run(
arg0,
arg1,
arg2...,
)
})
return _c
}
func (_c *AWSCodeCommitClient_ListRepositoriesWithContext_Call) Return(listRepositoriesOutput *codecommit.ListRepositoriesOutput, err error) *AWSCodeCommitClient_ListRepositoriesWithContext_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 {
_c.Call.Return(run)
return _c
}

View File

@@ -1,58 +1,16 @@
// Code generated by mockery v2.52.4. DO NOT EDIT.
// Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package mocks
import (
context "context"
request "github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
mock "github.com/stretchr/testify/mock"
resourcegroupstaggingapi "github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
)
// AWSTaggingClient is an autogenerated mock type for the AWSTaggingClient type
type AWSTaggingClient struct {
mock.Mock
}
// GetResourcesWithContext provides a mock function with given fields: _a0, _a1, _a2
func (_m *AWSTaggingClient) GetResourcesWithContext(_a0 context.Context, _a1 *resourcegroupstaggingapi.GetResourcesInput, _a2 ...request.Option) (*resourcegroupstaggingapi.GetResourcesOutput, error) {
_va := make([]interface{}, len(_a2))
for _i := range _a2 {
_va[_i] = _a2[_i]
}
var _ca []interface{}
_ca = append(_ca, _a0, _a1)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for GetResourcesWithContext")
}
var r0 *resourcegroupstaggingapi.GetResourcesOutput
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *resourcegroupstaggingapi.GetResourcesInput, ...request.Option) (*resourcegroupstaggingapi.GetResourcesOutput, error)); ok {
return rf(_a0, _a1, _a2...)
}
if rf, ok := ret.Get(0).(func(context.Context, *resourcegroupstaggingapi.GetResourcesInput, ...request.Option) *resourcegroupstaggingapi.GetResourcesOutput); ok {
r0 = rf(_a0, _a1, _a2...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*resourcegroupstaggingapi.GetResourcesOutput)
}
}
if rf, ok := ret.Get(1).(func(context.Context, *resourcegroupstaggingapi.GetResourcesInput, ...request.Option) error); ok {
r1 = rf(_a0, _a1, _a2...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// NewAWSTaggingClient creates a new instance of AWSTaggingClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewAWSTaggingClient(t interface {
@@ -66,3 +24,103 @@ func NewAWSTaggingClient(t interface {
return mock
}
// AWSTaggingClient is an autogenerated mock type for the AWSTaggingClient type
type AWSTaggingClient struct {
mock.Mock
}
type AWSTaggingClient_Expecter struct {
mock *mock.Mock
}
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]
}
var _ca []interface{}
_ca = append(_ca, v, getResourcesInput)
_ca = append(_ca, _va...)
ret := _mock.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for GetResourcesWithContext")
}
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(aws.Context, *resourcegroupstaggingapi.GetResourcesInput, ...request.Option) *resourcegroupstaggingapi.GetResourcesOutput); ok {
r0 = returnFunc(v, getResourcesInput, options...)
} 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...)
} 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 {
*mock.Call
}
// GetResourcesWithContext is a helper method to define mock.On call
// - v aws.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...)...)}
}
func (_c *AWSTaggingClient_GetResourcesWithContext_Call) Run(run func(v aws.Context, getResourcesInput *resourcegroupstaggingapi.GetResourcesInput, options ...request.Option)) *AWSTaggingClient_GetResourcesWithContext_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 aws.Context
if args[0] != nil {
arg0 = args[0].(aws.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)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(request.Option)
}
}
arg2 = variadicArgs
run(
arg0,
arg1,
arg2...,
)
})
return _c
}
func (_c *AWSTaggingClient_GetResourcesWithContext_Call) Return(getResourcesOutput *resourcegroupstaggingapi.GetResourcesOutput, err error) *AWSTaggingClient_GetResourcesWithContext_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 {
_c.Call.Return(run)
return _c
}

View File

@@ -8,8 +8,8 @@ import (
"strings"
"github.com/google/uuid"
"github.com/microsoft/azure-devops-go-api/azuredevops"
azureGit "github.com/microsoft/azure-devops-go-api/azuredevops/git"
"github.com/microsoft/azure-devops-go-api/azuredevops/v7"
azureGit "github.com/microsoft/azure-devops-go-api/azuredevops/v7/git"
)
const AZURE_DEVOPS_DEFAULT_URL = "https://dev.azure.com"
@@ -47,7 +47,6 @@ func (factory *devopsFactoryImpl) GetClient(ctx context.Context) (azureGit.Clien
type AzureDevOpsProvider struct {
organization string
teamProject string
accessToken string
clientFactory AzureDevOpsClientFactory
allBranches bool
}
@@ -69,7 +68,7 @@ func NewAzureDevOpsProvider(accessToken string, org string, url string, project
connection := azuredevops.NewPatConnection(devOpsURL, accessToken)
return &AzureDevOpsProvider{organization: org, teamProject: project, accessToken: accessToken, clientFactory: &devopsFactoryImpl{connection: connection}, allBranches: allBranches}, nil
return &AzureDevOpsProvider{organization: org, teamProject: project, clientFactory: &devopsFactoryImpl{connection: connection}, allBranches: allBranches}, nil
}
func (g *AzureDevOpsProvider) ListRepos(ctx context.Context, _ string) ([]*Repository, error) {

File diff suppressed because it is too large Load Diff

View File

@@ -12,8 +12,8 @@ import (
"github.com/stretchr/testify/require"
"k8s.io/utils/ptr"
"github.com/microsoft/azure-devops-go-api/azuredevops"
azureGit "github.com/microsoft/azure-devops-go-api/azuredevops/git"
"github.com/microsoft/azure-devops-go-api/azuredevops/v7"
azureGit "github.com/microsoft/azure-devops-go-api/azuredevops/v7/git"
azureMock "github.com/argoproj/argo-cd/v3/applicationset/services/scm_provider/azure_devops/git/mocks"
)

View File

@@ -350,6 +350,7 @@ func TestGetBranchesMissingDefault(t *testing.T) {
assert.Empty(t, r.Header.Get("Authorization"))
if r.RequestURI == "/rest/api/1.0/projects/PROJECT/repos/REPO/branches/default" {
http.Error(w, "Not found", http.StatusNotFound)
return
}
defaultHandler(t)(w, r)
}))
@@ -393,6 +394,7 @@ func TestGetBranchesErrorDefaultBranch(t *testing.T) {
assert.Empty(t, r.Header.Get("Authorization"))
if r.RequestURI == "/rest/api/1.0/projects/PROJECT/repos/REPO/branches/default" {
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
defaultHandler(t)(w, r)
}))
@@ -543,6 +545,7 @@ func TestListReposMissingDefaultBranch(t *testing.T) {
assert.Empty(t, r.Header.Get("Authorization"))
if r.RequestURI == "/rest/api/1.0/projects/PROJECT/repos/REPO/branches/default" {
http.Error(w, "Not found", http.StatusNotFound)
return
}
defaultHandler(t)(w, r)
}))
@@ -559,6 +562,7 @@ func TestListReposErrorDefaultBranch(t *testing.T) {
assert.Empty(t, r.Header.Get("Authorization"))
if r.RequestURI == "/rest/api/1.0/projects/PROJECT/repos/REPO/branches/default" {
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
defaultHandler(t)(w, r)
}))

View File

@@ -6,7 +6,9 @@ import (
"net/http"
"os"
"github.com/google/go-github/v66/github"
"github.com/google/go-github/v69/github"
appsetutils "github.com/argoproj/argo-cd/v3/applicationset/utils"
)
type GithubProvider struct {
@@ -17,15 +19,21 @@ type GithubProvider struct {
var _ SCMProviderService = &GithubProvider{}
func NewGithubProvider(organization string, token string, url string, allBranches bool) (*GithubProvider, error) {
func NewGithubProvider(organization string, token string, url string, allBranches bool, optionalHTTPClient ...*http.Client) (*GithubProvider, error) {
// Undocumented environment variable to set a default token, to be used in testing to dodge anonymous rate limits.
if token == "" {
token = os.Getenv("GITHUB_TOKEN")
}
httpClient := &http.Client{}
var client *github.Client
httpClient := appsetutils.GetOptionalHTTPClient(optionalHTTPClient...)
if url == "" {
client = github.NewClient(httpClient).WithAuthToken(token)
if token == "" {
client = github.NewClient(httpClient)
} else {
client = github.NewClient(httpClient).WithAuthToken(token)
}
} else {
var err error
client, err = github.NewClient(httpClient).WithEnterpriseURLs(url, url)

View File

@@ -1,12 +1,16 @@
package scm_provider
import (
"net/http"
"github.com/argoproj/argo-cd/v3/applicationset/services/github_app_auth"
"github.com/argoproj/argo-cd/v3/applicationset/services/internal/github_app"
appsetutils "github.com/argoproj/argo-cd/v3/applicationset/utils"
)
func NewGithubAppProviderFor(g github_app_auth.Authentication, organization string, url string, allBranches bool) (*GithubProvider, error) {
client, err := github_app.Client(g, url)
func NewGithubAppProviderFor(g github_app_auth.Authentication, organization string, url string, allBranches bool, optionalHTTPClient ...*http.Client) (*GithubProvider, error) {
httpClient := appsetutils.GetOptionalHTTPClient(optionalHTTPClient...)
client, err := github_app.Client(g, url, httpClient)
if err != nil {
return nil, err
}

View File

@@ -267,6 +267,14 @@ func TestGithubListRepos(t *testing.T) {
}
}
/*
metricsCtx := &services.MetricsContext{
AppSetNamespace: "test-ns",
AppSetName: "test-appset",
}
httpClient := services.NewGitHubMetricsClient(metricsCtx)
*/
func TestGithubHasPath(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
githubMockHandler(t)(w, r)

View File

@@ -104,6 +104,7 @@ func (g *GitlabProvider) ListRepos(_ context.Context, cloneProtocol string) ([]*
var repoLabels []string
if len(gitlabRepo.Topics) == 0 {
// fallback to for gitlab prior to 14.5
//nolint:staticcheck
repoLabels = gitlabRepo.TagList
} else {
repoLabels = gitlabRepo.Topics

View File

@@ -172,9 +172,10 @@ func getApplicableFilters(filters []*Filter) map[FilterType][]*Filter {
FilterTypeRepo: {},
}
for _, filter := range filters {
if filter.FilterType == FilterTypeBranch {
switch filter.FilterType {
case FilterTypeBranch:
filterMap[FilterTypeBranch] = append(filterMap[FilterTypeBranch], filter)
} else if filter.FilterType == FilterTypeRepo {
case FilterTypeRepo:
filterMap[FilterTypeRepo] = append(filterMap[FilterTypeRepo], filter)
}
}

View File

@@ -17,7 +17,7 @@ func BuildResourceStatus(statusMap map[string]argov1alpha1.ResourceStatus, apps
status.Name = app.Name
status.Namespace = app.Namespace
status.Status = app.Status.Sync.Status
status.Health = app.Status.Health.DeepCopy()
status.Health = &argov1alpha1.HealthStatus{Status: app.Status.Health.Status}
statusMap[app.Name] = status
}

View File

@@ -6,8 +6,8 @@ import (
"k8s.io/apimachinery/pkg/labels"
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
. "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
. "github.com/argoproj/argo-cd/v3/pkg/client/listers/application/v1alpha1"
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
listers "github.com/argoproj/argo-cd/v3/pkg/client/listers/application/v1alpha1"
)
// Implements AppsetLister interface with controller-runtime client
@@ -15,16 +15,16 @@ type AppsetLister struct {
Client ctrlclient.Client
}
func NewAppsetLister(client ctrlclient.Client) ApplicationSetLister {
func NewAppsetLister(client ctrlclient.Client) listers.ApplicationSetLister {
return &AppsetLister{Client: client}
}
func (l *AppsetLister) List(_ labels.Selector) (ret []*ApplicationSet, err error) {
func (l *AppsetLister) List(_ labels.Selector) (ret []*v1alpha1.ApplicationSet, err error) {
return clientListAppsets(l.Client, ctrlclient.ListOptions{})
}
// ApplicationSets returns an object that can list and get ApplicationSets.
func (l *AppsetLister) ApplicationSets(namespace string) ApplicationSetNamespaceLister {
func (l *AppsetLister) ApplicationSets(namespace string) listers.ApplicationSetNamespaceLister {
return &appsetNamespaceLister{
Client: l.Client,
Namespace: namespace,
@@ -37,19 +37,19 @@ type appsetNamespaceLister struct {
Namespace string
}
func (n *appsetNamespaceLister) List(_ labels.Selector) (ret []*ApplicationSet, err error) {
func (n *appsetNamespaceLister) List(_ labels.Selector) (ret []*v1alpha1.ApplicationSet, err error) {
return clientListAppsets(n.Client, ctrlclient.ListOptions{Namespace: n.Namespace})
}
func (n *appsetNamespaceLister) Get(_ string) (*ApplicationSet, error) {
appset := ApplicationSet{}
func (n *appsetNamespaceLister) Get(_ string) (*v1alpha1.ApplicationSet, error) {
appset := v1alpha1.ApplicationSet{}
err := n.Client.Get(context.TODO(), ctrlclient.ObjectKeyFromObject(&appset), &appset)
return &appset, err
}
func clientListAppsets(client ctrlclient.Client, listOptions ctrlclient.ListOptions) (ret []*ApplicationSet, err error) {
var appsetlist ApplicationSetList
var results []*ApplicationSet
func clientListAppsets(client ctrlclient.Client, listOptions ctrlclient.ListOptions) (ret []*v1alpha1.ApplicationSet, err error) {
var appsetlist v1alpha1.ApplicationSetList
var results []*v1alpha1.ApplicationSet
err = client.List(context.TODO(), &appsetlist, &listOptions)

View File

@@ -79,10 +79,10 @@ func CreateOrUpdate(ctx context.Context, logCtx *log.Entry, c client.Client, ign
return a.Cmp(b) == 0
},
func(a, b metav1.MicroTime) bool {
return a.UTC() == b.UTC()
return a.UTC().Equal(b.UTC())
},
func(a, b metav1.Time) bool {
return a.UTC() == b.UTC()
return a.UTC().Equal(b.UTC())
},
func(a, b labels.Selector) bool {
return a.String() == b.String()

View File

@@ -13,6 +13,8 @@ import (
)
func Test_applyIgnoreDifferences(t *testing.T) {
t.Parallel()
appMeta := metav1.TypeMeta{
APIVersion: v1alpha1.ApplicationSchemaGroupVersionKind.GroupVersion().String(),
Kind: v1alpha1.ApplicationSchemaGroupVersionKind.Kind,

View File

@@ -13,20 +13,11 @@ func ConvertToMapStringString(mapStringInterface map[string]any) map[string]stri
return mapStringString
}
func ConvertToMapStringInterface(mapStringString map[string]string) map[string]any {
mapStringInterface := make(map[string]any, len(mapStringString))
for key, value := range mapStringString {
mapStringInterface[key] = value
}
return mapStringInterface
}
func CombineStringMaps(aSI map[string]any, bSI map[string]any) (map[string]string, error) {
func CombineStringMaps(aSI map[string]any, bSI map[string]any) (map[string]any, error) {
a := ConvertToMapStringString(aSI)
b := ConvertToMapStringString(bSI)
res := map[string]string{}
res := map[string]any{}
for k, v := range a {
res[k] = v
@@ -42,21 +33,3 @@ func CombineStringMaps(aSI map[string]any, bSI map[string]any) (map[string]strin
return res, nil
}
// CombineStringMapsAllowDuplicates merges two maps. Where there are duplicates, take the latter map's value.
func CombineStringMapsAllowDuplicates(aSI map[string]any, bSI map[string]any) (map[string]string, error) {
a := ConvertToMapStringString(aSI)
b := ConvertToMapStringString(bSI)
res := map[string]string{}
for k, v := range a {
res[k] = v
}
for k, v := range b {
res[k] = v
}
return res, nil
}

View File

@@ -9,32 +9,34 @@ import (
)
func TestCombineStringMaps(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
left map[string]any
right map[string]any
expected map[string]string
expected map[string]any
expectedErr error
}{
{
name: "combines the maps",
left: map[string]any{"foo": "bar"},
right: map[string]any{"a": "b"},
expected: map[string]string{"a": "b", "foo": "bar"},
expected: map[string]any{"a": "b", "foo": "bar"},
expectedErr: nil,
},
{
name: "fails if keys are the same but value isn't",
left: map[string]any{"foo": "bar", "a": "fail"},
right: map[string]any{"a": "b", "c": "d"},
expected: map[string]string{"a": "b", "foo": "bar"},
expected: map[string]any{"a": "b", "foo": "bar"},
expectedErr: errors.New("found duplicate key a with different value, a: fail ,b: b"),
},
{
name: "pass if keys & values are the same",
left: map[string]any{"foo": "bar", "a": "b"},
right: map[string]any{"a": "b", "c": "d"},
expected: map[string]string{"a": "b", "c": "d", "foo": "bar"},
expected: map[string]any{"a": "b", "c": "d", "foo": "bar"},
expectedErr: nil,
},
}

View File

@@ -1,76 +1,14 @@
// Code generated by mockery v2.52.4. DO NOT EDIT.
// Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package mocks
import (
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
mock "github.com/stretchr/testify/mock"
v1alpha1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
)
// Renderer is an autogenerated mock type for the Renderer type
type Renderer struct {
mock.Mock
}
// RenderTemplateParams provides a mock function with given fields: tmpl, syncPolicy, params, useGoTemplate, goTemplateOptions
func (_m *Renderer) RenderTemplateParams(tmpl *v1alpha1.Application, syncPolicy *v1alpha1.ApplicationSetSyncPolicy, params map[string]interface{}, useGoTemplate bool, goTemplateOptions []string) (*v1alpha1.Application, error) {
ret := _m.Called(tmpl, syncPolicy, params, useGoTemplate, goTemplateOptions)
if len(ret) == 0 {
panic("no return value specified for RenderTemplateParams")
}
var r0 *v1alpha1.Application
var r1 error
if rf, ok := ret.Get(0).(func(*v1alpha1.Application, *v1alpha1.ApplicationSetSyncPolicy, map[string]interface{}, bool, []string) (*v1alpha1.Application, error)); ok {
return rf(tmpl, syncPolicy, params, useGoTemplate, goTemplateOptions)
}
if rf, ok := ret.Get(0).(func(*v1alpha1.Application, *v1alpha1.ApplicationSetSyncPolicy, map[string]interface{}, bool, []string) *v1alpha1.Application); ok {
r0 = rf(tmpl, syncPolicy, params, useGoTemplate, goTemplateOptions)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*v1alpha1.Application)
}
}
if rf, ok := ret.Get(1).(func(*v1alpha1.Application, *v1alpha1.ApplicationSetSyncPolicy, map[string]interface{}, bool, []string) error); ok {
r1 = rf(tmpl, syncPolicy, params, useGoTemplate, goTemplateOptions)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Replace provides a mock function with given fields: tmpl, replaceMap, useGoTemplate, goTemplateOptions
func (_m *Renderer) Replace(tmpl string, replaceMap map[string]interface{}, useGoTemplate bool, goTemplateOptions []string) (string, error) {
ret := _m.Called(tmpl, replaceMap, useGoTemplate, goTemplateOptions)
if len(ret) == 0 {
panic("no return value specified for Replace")
}
var r0 string
var r1 error
if rf, ok := ret.Get(0).(func(string, map[string]interface{}, bool, []string) (string, error)); ok {
return rf(tmpl, replaceMap, useGoTemplate, goTemplateOptions)
}
if rf, ok := ret.Get(0).(func(string, map[string]interface{}, bool, []string) string); ok {
r0 = rf(tmpl, replaceMap, useGoTemplate, goTemplateOptions)
} else {
r0 = ret.Get(0).(string)
}
if rf, ok := ret.Get(1).(func(string, map[string]interface{}, bool, []string) error); ok {
r1 = rf(tmpl, replaceMap, useGoTemplate, goTemplateOptions)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// NewRenderer creates a new instance of Renderer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewRenderer(t interface {
@@ -84,3 +22,180 @@ func NewRenderer(t interface {
return mock
}
// Renderer is an autogenerated mock type for the Renderer type
type Renderer struct {
mock.Mock
}
type Renderer_Expecter struct {
mock *mock.Mock
}
func (_m *Renderer) EXPECT() *Renderer_Expecter {
return &Renderer_Expecter{mock: &_m.Mock}
}
// RenderTemplateParams provides a mock function for the type Renderer
func (_mock *Renderer) RenderTemplateParams(tmpl *v1alpha1.Application, syncPolicy *v1alpha1.ApplicationSetSyncPolicy, params map[string]any, useGoTemplate bool, goTemplateOptions []string) (*v1alpha1.Application, error) {
ret := _mock.Called(tmpl, syncPolicy, params, useGoTemplate, goTemplateOptions)
if len(ret) == 0 {
panic("no return value specified for RenderTemplateParams")
}
var r0 *v1alpha1.Application
var r1 error
if returnFunc, ok := ret.Get(0).(func(*v1alpha1.Application, *v1alpha1.ApplicationSetSyncPolicy, map[string]any, bool, []string) (*v1alpha1.Application, error)); ok {
return returnFunc(tmpl, syncPolicy, params, useGoTemplate, goTemplateOptions)
}
if returnFunc, ok := ret.Get(0).(func(*v1alpha1.Application, *v1alpha1.ApplicationSetSyncPolicy, map[string]any, bool, []string) *v1alpha1.Application); ok {
r0 = returnFunc(tmpl, syncPolicy, params, useGoTemplate, goTemplateOptions)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*v1alpha1.Application)
}
}
if returnFunc, ok := ret.Get(1).(func(*v1alpha1.Application, *v1alpha1.ApplicationSetSyncPolicy, map[string]any, bool, []string) error); ok {
r1 = returnFunc(tmpl, syncPolicy, params, useGoTemplate, goTemplateOptions)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Renderer_RenderTemplateParams_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RenderTemplateParams'
type Renderer_RenderTemplateParams_Call struct {
*mock.Call
}
// RenderTemplateParams is a helper method to define mock.On call
// - tmpl *v1alpha1.Application
// - syncPolicy *v1alpha1.ApplicationSetSyncPolicy
// - params map[string]any
// - useGoTemplate bool
// - goTemplateOptions []string
func (_e *Renderer_Expecter) RenderTemplateParams(tmpl interface{}, syncPolicy interface{}, params interface{}, useGoTemplate interface{}, goTemplateOptions interface{}) *Renderer_RenderTemplateParams_Call {
return &Renderer_RenderTemplateParams_Call{Call: _e.mock.On("RenderTemplateParams", tmpl, syncPolicy, params, useGoTemplate, goTemplateOptions)}
}
func (_c *Renderer_RenderTemplateParams_Call) Run(run func(tmpl *v1alpha1.Application, syncPolicy *v1alpha1.ApplicationSetSyncPolicy, params map[string]any, useGoTemplate bool, goTemplateOptions []string)) *Renderer_RenderTemplateParams_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 *v1alpha1.Application
if args[0] != nil {
arg0 = args[0].(*v1alpha1.Application)
}
var arg1 *v1alpha1.ApplicationSetSyncPolicy
if args[1] != nil {
arg1 = args[1].(*v1alpha1.ApplicationSetSyncPolicy)
}
var arg2 map[string]any
if args[2] != nil {
arg2 = args[2].(map[string]any)
}
var arg3 bool
if args[3] != nil {
arg3 = args[3].(bool)
}
var arg4 []string
if args[4] != nil {
arg4 = args[4].([]string)
}
run(
arg0,
arg1,
arg2,
arg3,
arg4,
)
})
return _c
}
func (_c *Renderer_RenderTemplateParams_Call) Return(application *v1alpha1.Application, err error) *Renderer_RenderTemplateParams_Call {
_c.Call.Return(application, err)
return _c
}
func (_c *Renderer_RenderTemplateParams_Call) RunAndReturn(run func(tmpl *v1alpha1.Application, syncPolicy *v1alpha1.ApplicationSetSyncPolicy, params map[string]any, useGoTemplate bool, goTemplateOptions []string) (*v1alpha1.Application, error)) *Renderer_RenderTemplateParams_Call {
_c.Call.Return(run)
return _c
}
// Replace provides a mock function for the type Renderer
func (_mock *Renderer) Replace(tmpl string, replaceMap map[string]any, useGoTemplate bool, goTemplateOptions []string) (string, error) {
ret := _mock.Called(tmpl, replaceMap, useGoTemplate, goTemplateOptions)
if len(ret) == 0 {
panic("no return value specified for Replace")
}
var r0 string
var r1 error
if returnFunc, ok := ret.Get(0).(func(string, map[string]any, bool, []string) (string, error)); ok {
return returnFunc(tmpl, replaceMap, useGoTemplate, goTemplateOptions)
}
if returnFunc, ok := ret.Get(0).(func(string, map[string]any, bool, []string) string); ok {
r0 = returnFunc(tmpl, replaceMap, useGoTemplate, goTemplateOptions)
} else {
r0 = ret.Get(0).(string)
}
if returnFunc, ok := ret.Get(1).(func(string, map[string]any, bool, []string) error); ok {
r1 = returnFunc(tmpl, replaceMap, useGoTemplate, goTemplateOptions)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Renderer_Replace_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Replace'
type Renderer_Replace_Call struct {
*mock.Call
}
// Replace is a helper method to define mock.On call
// - tmpl string
// - replaceMap map[string]any
// - useGoTemplate bool
// - goTemplateOptions []string
func (_e *Renderer_Expecter) Replace(tmpl interface{}, replaceMap interface{}, useGoTemplate interface{}, goTemplateOptions interface{}) *Renderer_Replace_Call {
return &Renderer_Replace_Call{Call: _e.mock.On("Replace", tmpl, replaceMap, useGoTemplate, goTemplateOptions)}
}
func (_c *Renderer_Replace_Call) Run(run func(tmpl string, replaceMap map[string]any, useGoTemplate bool, goTemplateOptions []string)) *Renderer_Replace_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
var arg1 map[string]any
if args[1] != nil {
arg1 = args[1].(map[string]any)
}
var arg2 bool
if args[2] != nil {
arg2 = args[2].(bool)
}
var arg3 []string
if args[3] != nil {
arg3 = args[3].([]string)
}
run(
arg0,
arg1,
arg2,
arg3,
)
})
return _c
}
func (_c *Renderer_Replace_Call) Return(s string, err error) *Renderer_Replace_Call {
_c.Call.Return(s, err)
return _c
}
func (_c *Renderer_Replace_Call) RunAndReturn(run func(tmpl string, replaceMap map[string]any, useGoTemplate bool, goTemplateOptions []string) (string, error)) *Renderer_Replace_Call {
_c.Call.Return(run)
return _c
}

View File

@@ -8,6 +8,7 @@ import (
"errors"
"fmt"
"io"
"net/http"
"os"
"reflect"
"regexp"
@@ -58,14 +59,14 @@ func copyValueIntoUnexported(destination, value reflect.Value) {
Set(value)
}
func copyUnexported(copy, original reflect.Value) {
func copyUnexported(destination, original reflect.Value) {
unexported := reflect.NewAt(original.Type(), unsafe.Pointer(original.UnsafeAddr())).Elem()
copyValueIntoUnexported(copy, unexported)
copyValueIntoUnexported(destination, unexported)
}
func IsJSONStr(str string) bool {
str = strings.TrimSpace(str)
return len(str) > 0 && str[0] == '{'
return str != "" && str[0] == '{'
}
func ConvertYAMLToJSON(str string) (string, error) {
@@ -81,7 +82,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(copy, original reflect.Value, replaceMap map[string]any, useGoTemplate bool, goTemplateOptions []string) error {
func (r *Render) deeplyReplace(destination, original reflect.Value, replaceMap map[string]any, useGoTemplate bool, goTemplateOptions []string) 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
@@ -96,12 +97,12 @@ func (r *Render) deeplyReplace(copy, original reflect.Value, replaceMap map[stri
}
// Allocate a new object and set the pointer to it
if originalValue.CanSet() {
copy.Set(reflect.New(originalValue.Type()))
destination.Set(reflect.New(originalValue.Type()))
} else {
copyUnexported(copy, original)
copyUnexported(destination, original)
}
// Unwrap the newly created pointer
if err := r.deeplyReplace(copy.Elem(), originalValue, replaceMap, useGoTemplate, goTemplateOptions); err != nil {
if err := r.deeplyReplace(destination.Elem(), originalValue, replaceMap, useGoTemplate, goTemplateOptions); err != nil {
// Not wrapping the error, since this is a recursive function. Avoids excessively long error messages.
return err
}
@@ -126,7 +127,7 @@ func (r *Render) deeplyReplace(copy, original reflect.Value, replaceMap map[stri
// Not wrapping the error, since this is a recursive function. Avoids excessively long error messages.
return err
}
copy.Set(copyValue)
destination.Set(copyValue)
}
// If it is a struct we translate each field
@@ -135,7 +136,7 @@ func (r *Render) deeplyReplace(copy, original reflect.Value, replaceMap map[stri
currentType := fmt.Sprintf("%s.%s", original.Type().Field(i).Name, original.Type().PkgPath())
// specific case time
if currentType == "time.Time" {
copy.Field(i).Set(original.Field(i))
destination.Field(i).Set(original.Field(i))
} else if currentType == "Raw.k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" || currentType == "Raw.k8s.io/apimachinery/pkg/runtime" {
var unmarshaled any
originalBytes := original.Field(i).Bytes()
@@ -158,8 +159,8 @@ func (r *Render) deeplyReplace(copy, original reflect.Value, replaceMap map[stri
if err != nil {
return fmt.Errorf("failed to marshal templated JSON field: %w", err)
}
copy.Field(i).Set(reflect.ValueOf(data))
} else if err := r.deeplyReplace(copy.Field(i), original.Field(i), replaceMap, useGoTemplate, goTemplateOptions); err != nil {
destination.Field(i).Set(reflect.ValueOf(data))
} else if err := r.deeplyReplace(destination.Field(i), original.Field(i), replaceMap, useGoTemplate, goTemplateOptions); err != nil {
// Not wrapping the error, since this is a recursive function. Avoids excessively long error messages.
return err
}
@@ -167,14 +168,14 @@ func (r *Render) deeplyReplace(copy, original reflect.Value, replaceMap map[stri
// If it is a slice we create a new slice and translate each element
case reflect.Slice:
if copy.CanSet() {
copy.Set(reflect.MakeSlice(original.Type(), original.Len(), original.Cap()))
if destination.CanSet() {
destination.Set(reflect.MakeSlice(original.Type(), original.Len(), original.Cap()))
} else {
copyValueIntoUnexported(copy, reflect.MakeSlice(original.Type(), original.Len(), original.Cap()))
copyValueIntoUnexported(destination, reflect.MakeSlice(original.Type(), original.Len(), original.Cap()))
}
for i := 0; i < original.Len(); i++ {
if err := r.deeplyReplace(copy.Index(i), original.Index(i), replaceMap, useGoTemplate, goTemplateOptions); err != nil {
if err := r.deeplyReplace(destination.Index(i), original.Index(i), replaceMap, useGoTemplate, goTemplateOptions); err != nil {
// Not wrapping the error, since this is a recursive function. Avoids excessively long error messages.
return err
}
@@ -182,10 +183,10 @@ func (r *Render) deeplyReplace(copy, original reflect.Value, replaceMap map[stri
// If it is a map we create a new map and translate each value
case reflect.Map:
if copy.CanSet() {
copy.Set(reflect.MakeMap(original.Type()))
if destination.CanSet() {
destination.Set(reflect.MakeMap(original.Type()))
} else {
copyValueIntoUnexported(copy, reflect.MakeMap(original.Type()))
copyValueIntoUnexported(destination, reflect.MakeMap(original.Type()))
}
for _, key := range original.MapKeys() {
originalValue := original.MapIndex(key)
@@ -210,7 +211,7 @@ func (r *Render) deeplyReplace(copy, original reflect.Value, replaceMap map[stri
key = reflect.ValueOf(templatedKey)
}
copy.SetMapIndex(key, copyValue)
destination.SetMapIndex(key, copyValue)
}
// Otherwise we cannot traverse anywhere so this finishes the recursion
@@ -222,19 +223,19 @@ func (r *Render) deeplyReplace(copy, original reflect.Value, replaceMap map[stri
// Not wrapping the error, since this is a recursive function. Avoids excessively long error messages.
return err
}
if copy.CanSet() {
copy.SetString(templated)
if destination.CanSet() {
destination.SetString(templated)
} else {
copyValueIntoUnexported(copy, reflect.ValueOf(templated))
copyValueIntoUnexported(destination, reflect.ValueOf(templated))
}
return nil
// And everything else will simply be taken from the original
default:
if copy.CanSet() {
copy.Set(original)
if destination.CanSet() {
destination.Set(original)
} else {
copyUnexported(copy, original)
copyUnexported(destination, original)
}
}
return nil
@@ -260,13 +261,13 @@ func (r *Render) RenderTemplateParams(tmpl *argoappsv1.Application, syncPolicy *
}
original := reflect.ValueOf(tmpl)
copy := reflect.New(original.Type()).Elem()
destination := reflect.New(original.Type()).Elem()
if err := r.deeplyReplace(copy, original, params, useGoTemplate, goTemplateOptions); err != nil {
if err := r.deeplyReplace(destination, original, params, useGoTemplate, goTemplateOptions); err != nil {
return nil, err
}
replacedTmpl := copy.Interface().(*argoappsv1.Application)
replacedTmpl := destination.Interface().(*argoappsv1.Application)
// Add the 'resources-finalizer' finalizer if:
// The template application doesn't have any finalizers, and:
@@ -274,8 +275,8 @@ func (r *Render) RenderTemplateParams(tmpl *argoappsv1.Application, syncPolicy *
// b) there IS a syncPolicy, but preserveResourcesOnDeletion is set to false
// See TestRenderTemplateParamsFinalizers in util_test.go for test-based definition of behaviour
if (syncPolicy == nil || !syncPolicy.PreserveResourcesOnDeletion) &&
len(replacedTmpl.ObjectMeta.Finalizers) == 0 {
replacedTmpl.ObjectMeta.Finalizers = []string{"resources-finalizer.argocd.argoproj.io"}
len(replacedTmpl.Finalizers) == 0 {
replacedTmpl.Finalizers = []string{argoappsv1.ResourcesFinalizerName}
}
return replacedTmpl, nil
@@ -291,13 +292,13 @@ func (r *Render) RenderGeneratorParams(gen *argoappsv1.ApplicationSetGenerator,
}
original := reflect.ValueOf(gen)
copy := reflect.New(original.Type()).Elem()
destination := reflect.New(original.Type()).Elem()
if err := r.deeplyReplace(copy, original, params, useGoTemplate, goTemplateOptions); err != nil {
if err := r.deeplyReplace(destination, original, params, useGoTemplate, goTemplateOptions); err != nil {
return nil, fmt.Errorf("failed to replace parameters in generator: %w", err)
}
replacedGen := copy.Interface().(*argoappsv1.ApplicationSetGenerator)
replacedGen := destination.Interface().(*argoappsv1.ApplicationSetGenerator)
return replacedGen, nil
}
@@ -335,8 +336,8 @@ func (r *Render) Replace(tmpl string, replaceMap map[string]any, useGoTemplate b
replacedTmpl := fstTmpl.ExecuteFuncString(func(w io.Writer, tag string) (int, error) {
trimmedTag := strings.TrimSpace(tag)
replacement, ok := replaceMap[trimmedTag].(string)
if len(trimmedTag) == 0 || !ok {
return w.Write([]byte(fmt.Sprintf("{{%s}}", tag)))
if trimmedTag == "" || !ok {
return fmt.Fprintf(w, "{{%s}}", tag)
}
return w.Write([]byte(replacement))
})
@@ -353,12 +354,12 @@ func CheckInvalidGenerators(applicationSetInfo *argoappsv1.ApplicationSet) error
gnames = append(gnames, n)
}
sort.Strings(gnames)
aname := applicationSetInfo.ObjectMeta.Name
aname := applicationSetInfo.Name
msg := "ApplicationSet %s contains unrecognized generators: %s"
errorMessage = fmt.Errorf(msg, aname, strings.Join(gnames, ", "))
log.Warnf(msg, aname, strings.Join(gnames, ", "))
} else if hasInvalidGenerators {
name := applicationSetInfo.ObjectMeta.Name
name := applicationSetInfo.Name
msg := "ApplicationSet %s contains unrecognized generators"
errorMessage = fmt.Errorf(msg, name)
log.Warnf(msg, name)
@@ -394,7 +395,7 @@ func invalidGenerators(applicationSetInfo *argoappsv1.ApplicationSet) (bool, map
func addInvalidGeneratorNames(names map[string]bool, applicationSetInfo *argoappsv1.ApplicationSet, index int) {
// The generator names are stored in the "kubectl.kubernetes.io/last-applied-configuration" annotation
config := applicationSetInfo.ObjectMeta.Annotations["kubectl.kubernetes.io/last-applied-configuration"]
config := applicationSetInfo.Annotations["kubectl.kubernetes.io/last-applied-configuration"]
var values map[string]any
err := json.Unmarshal([]byte(config), &values)
if err != nil {
@@ -526,3 +527,10 @@ func GetTlsConfig(scmRootCAPath string, insecure bool, caCerts []byte) *tls.Conf
}
return tlsConfig
}
func GetOptionalHTTPClient(optionalHTTPClient ...*http.Client) *http.Client {
if len(optionalHTTPClient) > 0 && optionalHTTPClient[0] != nil {
return optionalHTTPClient[0]
}
return &http.Client{}
}

View File

@@ -180,14 +180,14 @@ func TestRenderTemplateParams(t *testing.T) {
// the target field has been templated into the expected value
actualValue := *getPtrFunc(newApplication)
assert.Equal(t, test.expectedVal, actualValue, "Field '%s' had an unexpected value. expected: '%s' value: '%s'", fieldName, test.expectedVal, actualValue)
assert.Equal(t, "annotation-value", newApplication.ObjectMeta.Annotations["annotation-key"])
assert.Equal(t, "annotation-value2", newApplication.ObjectMeta.Annotations["annotation-key2"])
assert.Equal(t, "label-value", newApplication.ObjectMeta.Labels["label-key"])
assert.Equal(t, "label-value2", newApplication.ObjectMeta.Labels["label-key2"])
assert.Equal(t, "application-one", newApplication.ObjectMeta.Name)
assert.Equal(t, "default", newApplication.ObjectMeta.Namespace)
assert.Equal(t, newApplication.ObjectMeta.UID, types.UID("d546da12-06b7-4f9a-8ea2-3adb16a20e2b"))
assert.Equal(t, newApplication.ObjectMeta.CreationTimestamp, application.ObjectMeta.CreationTimestamp)
assert.Equal(t, "annotation-value", newApplication.Annotations["annotation-key"])
assert.Equal(t, "annotation-value2", newApplication.Annotations["annotation-key2"])
assert.Equal(t, "label-value", newApplication.Labels["label-key"])
assert.Equal(t, "label-value2", newApplication.Labels["label-key2"])
assert.Equal(t, "application-one", newApplication.Name)
assert.Equal(t, "default", newApplication.Namespace)
assert.Equal(t, newApplication.UID, types.UID("d546da12-06b7-4f9a-8ea2-3adb16a20e2b"))
assert.Equal(t, newApplication.CreationTimestamp, application.CreationTimestamp)
require.NoError(t, err)
}
})
@@ -627,14 +627,14 @@ func TestRenderTemplateParamsGoTemplate(t *testing.T) {
require.NoError(t, err)
actualValue := *getPtrFunc(newApplication)
assert.Equal(t, test.expectedVal, actualValue, "Field '%s' had an unexpected value. expected: '%s' value: '%s'", fieldName, test.expectedVal, actualValue)
assert.Equal(t, "annotation-value", newApplication.ObjectMeta.Annotations["annotation-key"])
assert.Equal(t, "annotation-value2", newApplication.ObjectMeta.Annotations["annotation-key2"])
assert.Equal(t, "label-value", newApplication.ObjectMeta.Labels["label-key"])
assert.Equal(t, "label-value2", newApplication.ObjectMeta.Labels["label-key2"])
assert.Equal(t, "application-one", newApplication.ObjectMeta.Name)
assert.Equal(t, "default", newApplication.ObjectMeta.Namespace)
assert.Equal(t, newApplication.ObjectMeta.UID, types.UID("d546da12-06b7-4f9a-8ea2-3adb16a20e2b"))
assert.Equal(t, newApplication.ObjectMeta.CreationTimestamp, application.ObjectMeta.CreationTimestamp)
assert.Equal(t, "annotation-value", newApplication.Annotations["annotation-key"])
assert.Equal(t, "annotation-value2", newApplication.Annotations["annotation-key2"])
assert.Equal(t, "label-value", newApplication.Labels["label-key"])
assert.Equal(t, "label-value2", newApplication.Labels["label-key2"])
assert.Equal(t, "application-one", newApplication.Name)
assert.Equal(t, "default", newApplication.Namespace)
assert.Equal(t, newApplication.UID, types.UID("d546da12-06b7-4f9a-8ea2-3adb16a20e2b"))
assert.Equal(t, newApplication.CreationTimestamp, application.CreationTimestamp)
}
}
})
@@ -687,8 +687,8 @@ func TestRenderTemplateKeys(t *testing.T) {
render := Render{}
newApplication, err := render.RenderTemplateParams(application, nil, params, false, nil)
require.NoError(t, err)
require.Contains(t, newApplication.ObjectMeta.Annotations, "annotation-some-key")
assert.Equal(t, "annotation-some-value", newApplication.ObjectMeta.Annotations["annotation-some-key"])
require.Contains(t, newApplication.Annotations, "annotation-some-key")
assert.Equal(t, "annotation-some-value", newApplication.Annotations["annotation-some-key"])
})
t.Run("gotemplate", func(t *testing.T) {
application := &argoappsv1.Application{
@@ -707,8 +707,8 @@ func TestRenderTemplateKeys(t *testing.T) {
render := Render{}
newApplication, err := render.RenderTemplateParams(application, nil, params, true, nil)
require.NoError(t, err)
require.Contains(t, newApplication.ObjectMeta.Annotations, "annotation-some-key")
assert.Equal(t, "annotation-some-value", newApplication.ObjectMeta.Annotations["annotation-some-key"])
require.Contains(t, newApplication.Annotations, "annotation-some-key")
assert.Equal(t, "annotation-some-value", newApplication.Annotations["annotation-some-key"])
})
}
@@ -752,35 +752,35 @@ func TestRenderTemplateParamsFinalizers(t *testing.T) {
},
{
testName: "background finalizer should be preserved",
existingFinalizers: []string{"resources-finalizer.argocd.argoproj.io/background"},
existingFinalizers: []string{argoappsv1.BackgroundPropagationPolicyFinalizer},
syncPolicy: nil,
expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io/background"},
expectedFinalizers: []string{argoappsv1.BackgroundPropagationPolicyFinalizer},
},
{
testName: "empty finalizer and empty sync should use standard finalizer",
existingFinalizers: nil,
syncPolicy: nil,
expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io"},
expectedFinalizers: []string{argoappsv1.ResourcesFinalizerName},
},
{
testName: "standard finalizer should be preserved",
existingFinalizers: []string{"resources-finalizer.argocd.argoproj.io"},
existingFinalizers: []string{argoappsv1.ResourcesFinalizerName},
syncPolicy: nil,
expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io"},
expectedFinalizers: []string{argoappsv1.ResourcesFinalizerName},
},
{
testName: "empty array finalizers should use standard finalizer",
existingFinalizers: []string{},
syncPolicy: nil,
expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io"},
expectedFinalizers: []string{argoappsv1.ResourcesFinalizerName},
},
{
testName: "non-nil sync policy should use standard finalizer",
existingFinalizers: nil,
syncPolicy: &argoappsv1.ApplicationSetSyncPolicy{},
expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io"},
expectedFinalizers: []string{argoappsv1.ResourcesFinalizerName},
},
{
testName: "preserveResourcesOnDeletion should not have a finalizer",
@@ -792,11 +792,11 @@ func TestRenderTemplateParamsFinalizers(t *testing.T) {
},
{
testName: "user-specified finalizer should overwrite preserveResourcesOnDeletion",
existingFinalizers: []string{"resources-finalizer.argocd.argoproj.io/background"},
existingFinalizers: []string{argoappsv1.BackgroundPropagationPolicyFinalizer},
syncPolicy: &argoappsv1.ApplicationSetSyncPolicy{
PreserveResourcesOnDeletion: true,
},
expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io/background"},
expectedFinalizers: []string{argoappsv1.BackgroundPropagationPolicyFinalizer},
},
} {
t.Run(c.testName, func(t *testing.T) {

View File

@@ -7,6 +7,7 @@ import (
"net/http"
"net/url"
"regexp"
"slices"
"strconv"
"strings"
"sync"
@@ -31,7 +32,6 @@ const payloadQueueSize = 50000
type WebhookHandler struct {
sync.WaitGroup // for testing
namespace string
github *github.Webhook
gitlab *gitlab.Webhook
azuredevops *azuredevops.Webhook
@@ -68,27 +68,26 @@ type prGeneratorGitlabInfo struct {
APIHostname string
}
func NewWebhookHandler(namespace string, webhookParallelism int, argocdSettingsMgr *argosettings.SettingsManager, client client.Client, generators map[string]generators.Generator) (*WebhookHandler, error) {
func NewWebhookHandler(webhookParallelism int, argocdSettingsMgr *argosettings.SettingsManager, client client.Client, generators map[string]generators.Generator) (*WebhookHandler, error) {
// register the webhook secrets stored under "argocd-secret" for verifying incoming payloads
argocdSettings, err := argocdSettingsMgr.GetSettings()
if err != nil {
return nil, fmt.Errorf("Failed to get argocd settings: %w", err)
return nil, fmt.Errorf("failed to get argocd settings: %w", err)
}
githubHandler, err := github.New(github.Options.Secret(argocdSettings.WebhookGitHubSecret))
if err != nil {
return nil, fmt.Errorf("Unable to init GitHub webhook: %w", err)
return nil, fmt.Errorf("unable to init GitHub webhook: %w", err)
}
gitlabHandler, err := gitlab.New(gitlab.Options.Secret(argocdSettings.WebhookGitLabSecret))
if err != nil {
return nil, fmt.Errorf("Unable to init GitLab webhook: %w", err)
return nil, fmt.Errorf("unable to init GitLab webhook: %w", err)
}
azuredevopsHandler, err := azuredevops.New(azuredevops.Options.BasicAuth(argocdSettings.WebhookAzureDevOpsUsername, argocdSettings.WebhookAzureDevOpsPassword))
if err != nil {
return nil, fmt.Errorf("Unable to init Azure DevOps webhook: %w", err)
return nil, fmt.Errorf("unable to init Azure DevOps webhook: %w", err)
}
webhookHandler := &WebhookHandler{
namespace: namespace,
github: githubHandler,
gitlab: gitlabHandler,
azuredevops: azuredevopsHandler,
@@ -234,7 +233,7 @@ func getPRGeneratorInfo(payload any) *prGeneratorInfo {
var info prGeneratorInfo
switch payload := payload.(type) {
case github.PullRequestPayload:
if !isAllowedGithubPullRequestAction(payload.Action) {
if !slices.Contains(githubAllowedPullRequestActions, payload.Action) {
return nil
}
@@ -250,7 +249,7 @@ func getPRGeneratorInfo(payload any) *prGeneratorInfo {
APIRegexp: apiRegexp,
}
case gitlab.MergeRequestEventPayload:
if !isAllowedGitlabPullRequestAction(payload.ObjectAttributes.Action) {
if !slices.Contains(gitlabAllowedPullRequestActions, payload.ObjectAttributes.Action) {
return nil
}
@@ -266,7 +265,7 @@ func getPRGeneratorInfo(payload any) *prGeneratorInfo {
APIHostname: urlObj.Hostname(),
}
case azuredevops.GitPullRequestEvent:
if !isAllowedAzureDevOpsPullRequestAction(string(payload.EventType)) {
if !slices.Contains(azuredevopsAllowedPullRequestActions, string(payload.EventType)) {
return nil
}
@@ -311,33 +310,6 @@ var azuredevopsAllowedPullRequestActions = []string{
"git.pullrequest.updated",
}
func isAllowedGithubPullRequestAction(action string) bool {
for _, allow := range githubAllowedPullRequestActions {
if allow == action {
return true
}
}
return false
}
func isAllowedGitlabPullRequestAction(action string) bool {
for _, allow := range gitlabAllowedPullRequestActions {
if allow == action {
return true
}
}
return false
}
func isAllowedAzureDevOpsPullRequestAction(action string) bool {
for _, allow := range azuredevopsAllowedPullRequestActions {
if allow == action {
return true
}
}
return false
}
func shouldRefreshGitGenerator(gen *v1alpha1.GitGenerator, info *gitGeneratorInfo) bool {
if gen == nil || info == nil {
return false

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