diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..83a6855 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,29 @@ +# SOPS configuration for deploy-app-kargo-private +# Three age keys: admin (all access), dev (dev/test cluster), prod (prod cluster) +# +# admin: age1xmnaqlrjzpk5hl7uhel9sehqh7zdz8p59qte2myt97aqd7lyeuxszuess7 +# dev: age1ame2tp44sq9rmkqzqvxy77eu7qd2035kmlgcsfjfxj2jughv3clqlku03g +# prod: age16p0gwk8vt90vy2gm8jjca8rcyd2drv5526e997ukdelnv5ek8unqm0smuk + +creation_rules: + # Prod-specific secrets — admin + prod only + - path_regex: \.prod\.enc\.yaml$ + encrypted_regex: ^(password|token|secret|key|privateKey|admin-password|db-password|passwordHash|tokenSigningKey)$ + age: >- + age1xmnaqlrjzpk5hl7uhel9sehqh7zdz8p59qte2myt97aqd7lyeuxszuess7, + age16p0gwk8vt90vy2gm8jjca8rcyd2drv5526e997ukdelnv5ek8unqm0smuk + + # Dev-specific secrets — admin + dev only + - path_regex: \.dev\.enc\.yaml$ + encrypted_regex: ^(password|token|secret|key|privateKey|admin-password|db-password|passwordHash|tokenSigningKey)$ + age: >- + age1xmnaqlrjzpk5hl7uhel9sehqh7zdz8p59qte2myt97aqd7lyeuxszuess7, + age1ame2tp44sq9rmkqzqvxy77eu7qd2035kmlgcsfjfxj2jughv3clqlku03g + + # Shared secrets (e.g. kargo credentials) — all three keys + - path_regex: \.shared\.enc\.yaml$ + encrypted_regex: ^(password|token|secret|key|privateKey|admin-password|db-password|repoURL|username)$ + age: >- + age1xmnaqlrjzpk5hl7uhel9sehqh7zdz8p59qte2myt97aqd7lyeuxszuess7, + age1ame2tp44sq9rmkqzqvxy77eu7qd2035kmlgcsfjfxj2jughv3clqlku03g, + age16p0gwk8vt90vy2gm8jjca8rcyd2drv5526e997ukdelnv5ek8unqm0smuk diff --git a/README.md b/README.md index 4174bed..ee0f605 100644 --- a/README.md +++ b/README.md @@ -1 +1,24 @@ -# deploy-app-kargo-private \ No newline at end of file +# deploy-app-kargo-private + +Private ArgoCD ApplicationSet repository with SOPS-encrypted secrets. + +## Structure + +- `infra/` — Infrastructure apps (cert-manager, gitea, kargo, etc.) +- `ci/` — CI apps (gitea-runner, etc.) +- `kargo/` — Kargo pipeline definitions + encrypted credentials +- `.sops.yaml` — SOPS encryption rules (3 age keys: admin, dev, prod) + +## Encryption + +Secrets in `*.enc.yaml` files are encrypted with SOPS + age: +- `*.dev.enc.yaml` — decryptable by admin + dev keys +- `*.prod.enc.yaml` — decryptable by admin + prod keys +- `*.shared.enc.yaml` — decryptable by all three keys + +## Branches + +- `main` — source of truth +- `infra/stage/dev` — dev cluster (Kargo promotion) +- `infra/stage/test` — test stage (Kargo verification) +- `infra/stage/prod` — prod cluster (Kargo promotion via PR) diff --git a/ci/gitea-runner/config.yaml b/ci/gitea-runner/config.yaml new file mode 100644 index 0000000..80d0a1c --- /dev/null +++ b/ci/gitea-runner/config.yaml @@ -0,0 +1,10 @@ +{ + "name": "gitea-runner", + "namespace": "gitea-runner", + "step": "5", + "source": { + "repoURL": "https://github.com/Kargones/deploy-app-kargo-private.git", + "path": "ci/gitea-runner/manifests", + "targetRevision": "main" + } +} diff --git a/ci/gitea-runner/manifests/namespace.yaml b/ci/gitea-runner/manifests/namespace.yaml new file mode 100644 index 0000000..60f86b0 --- /dev/null +++ b/ci/gitea-runner/manifests/namespace.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: gitea-runner + labels: + name: gitea-runner diff --git a/ci/gitea-runner/manifests/runner.yaml b/ci/gitea-runner/manifests/runner.yaml new file mode 100644 index 0000000..4a0910f --- /dev/null +++ b/ci/gitea-runner/manifests/runner.yaml @@ -0,0 +1,79 @@ +# Gitea Actions runner (act_runner) +# Requires registration token in gitea-runner-token secret +# Token is generated in Gitea admin → Actions → Runners → Create new runner +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: gitea-runner-config + namespace: gitea-runner +data: + config.yaml: | + log: + level: info + runner: + file: .runner + capacity: 1 + timeout: 3h + labels: + - "ubuntu-latest:docker://node:20-bullseye" + - "ubuntu-22.04:docker://node:20-bullseye" + cache: + enabled: true + dir: "" + container: + network: "" + privileged: false + options: + workdir_parent: +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gitea-runner + namespace: gitea-runner + labels: + app: gitea-runner +spec: + replicas: 0 # Set to 1 after creating registration token + selector: + matchLabels: + app: gitea-runner + template: + metadata: + labels: + app: gitea-runner + spec: + containers: + - name: runner + image: gitea/act_runner:0.2.11 + env: + - name: GITEA_INSTANCE_URL + value: "http://gitea-http.gitea.svc.cluster.local:3000" + - name: GITEA_RUNNER_REGISTRATION_TOKEN + valueFrom: + secretKeyRef: + name: gitea-runner-token + key: token + optional: true + volumeMounts: + - name: config + mountPath: /config + readOnly: true + - name: data + mountPath: /data + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: "2" + memory: 2Gi + volumes: + - name: config + configMap: + name: gitea-runner-config + - name: data + emptyDir: {} + nodeSelector: + node-role.kubernetes.io/worker: "" diff --git a/infra/argo-rollouts/config.yaml b/infra/argo-rollouts/config.yaml new file mode 100644 index 0000000..c796de5 --- /dev/null +++ b/infra/argo-rollouts/config.yaml @@ -0,0 +1,13 @@ +{ + "name": "argo-rollouts", + "namespace": "argo-rollouts", + "step": "2", + "source": { + "repoURL": "https://argoproj.github.io/argo-helm", + "chart": "argo-rollouts", + "targetRevision": 2.40.6 + }, + "helm": { + "values": "dashboard:\n enabled: true\n" + } +} diff --git a/infra/cert-manager/config.yaml b/infra/cert-manager/config.yaml new file mode 100644 index 0000000..ae6ec3a --- /dev/null +++ b/infra/cert-manager/config.yaml @@ -0,0 +1,13 @@ +{ + "name": "cert-manager", + "namespace": "cert-manager", + "step": "1", + "source": { + "repoURL": "https://charts.jetstack.io", + "chart": "cert-manager", + "targetRevision": v1.19.4 + }, + "helm": { + "values": "crds:\n enabled: true\n" + } +} diff --git a/infra/gitea-custom/config.yaml b/infra/gitea-custom/config.yaml new file mode 100644 index 0000000..d6ce90f --- /dev/null +++ b/infra/gitea-custom/config.yaml @@ -0,0 +1,10 @@ +{ + "name": "gitea-custom", + "namespace": "gitea", + "step": "6", + "source": { + "repoURL": "https://github.com/Kargones/deploy-app-kargo-private.git", + "path": "infra/gitea-custom/manifests", + "targetRevision": "main" + } +} diff --git a/infra/gitea-custom/manifests/disable-cache.yaml b/infra/gitea-custom/manifests/disable-cache.yaml new file mode 100644 index 0000000..196459d --- /dev/null +++ b/infra/gitea-custom/manifests/disable-cache.yaml @@ -0,0 +1,16 @@ +# Override Gitea cache/session to use memory (no redis/valkey) +# Mount this ConfigMap as /data/gitea/conf/app.ini override +apiVersion: v1 +kind: ConfigMap +metadata: + name: gitea-disable-cache + namespace: gitea +data: + _10-cache.ini: | + [cache] + ENABLED = false + ADAPTER = memory + INTERVAL = 0 + + [session] + PROVIDER = memory diff --git a/infra/gitea/config.yaml b/infra/gitea/config.yaml new file mode 100644 index 0000000..367bcf5 --- /dev/null +++ b/infra/gitea/config.yaml @@ -0,0 +1,13 @@ +{ + "name": "gitea", + "namespace": "gitea", + "step": "4", + "source": { + "repoURL": "https://dl.gitea.com/charts", + "chart": "gitea", + "targetRevision": "12.5.0" + }, + "helm": { + "values": "gitea:\n admin:\n existingSecret: gitea-admin\n config:\n server:\n ROOT_URL: \"https://gitea.k3s.e2e.local\"\n DOMAIN: \"k3s.e2e.local\"\n SSH_DOMAIN: \"gitea.k3s.e2e.local\"\n SSH_PORT: 2222\n service:\n DISABLE_REGISTRATION: false\n actions:\n ENABLED: \"true\"\n cache:\n ENABLED: false\n ADAPTER: memory\n session:\n PROVIDER: memory\n\ningress:\n enabled: false\n\npostgresql:\n enabled: true\n image:\n repository: bitnamilegacy/postgresql\n tag: \"17\"\n\npostgresql-ha:\n enabled: false\n\nmemcached:\n enabled: false\n\nredis-cluster:\n enabled: false\n\nredis:\n enabled: false\n\nvalkey-cluster:\n enabled: false\n\nimage:\n rootless: false\n" + } +} diff --git a/infra/gitea/values/secret-values.dev.enc.yaml b/infra/gitea/values/secret-values.dev.enc.yaml new file mode 100644 index 0000000..0690cd7 --- /dev/null +++ b/infra/gitea/values/secret-values.dev.enc.yaml @@ -0,0 +1,27 @@ +# Gitea secrets for dev/test cluster +admin-password: ENC[AES256_GCM,data:Nh7IDhZbJxOYjat8JhRoWtQ=,iv:mDtUOdjiKxvTTKaWNQ6bUQ2rCbV9Ule25IN5AVBTrp0=,tag:FxMWUvu82HusjtPBmEtwcA==,type:str] +db-password: ENC[AES256_GCM,data:qRZjNRGr/oJVzYTz6Kv0sZ7Sbns=,iv:V03c8IrsLZzJck5ZqrXS46LydbGPtLBwkjjGQI0zkv4=,tag:pxDpAbekwwOw9yiqMwl2QA==,type:str] +sops: + age: + - recipient: age1xmnaqlrjzpk5hl7uhel9sehqh7zdz8p59qte2myt97aqd7lyeuxszuess7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqdWFvNXF3QXpnbjFsbHhn + dmdnRmRwWnpkUVlRSHlEZXdXT2FoeVVVejFNCkZ0UGp5YWZ2TThEUnZPOVNqVjJR + S0lXSGxSSFF3ZWhUM2NMWW9MZUszZnMKLS0tIEowWHo5SUFMMDFNY1lWY3NuNnJN + OERJZklLT1RnSDc4VjdaQ0F3cVRTaGsKYIfYSv4In5YiGs2/KWX1oPqOoiUxwVUl + jROG2UecsSjhKq6XdX+KVYmcSKhy1ljPjHaL+t3MmSNE6+jJpMpDvQ== + -----END AGE ENCRYPTED FILE----- + - recipient: age1ame2tp44sq9rmkqzqvxy77eu7qd2035kmlgcsfjfxj2jughv3clqlku03g + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBUNzZSWE1NcTR1blQ5TWxH + N0k2YWNOdTA4WHZXQ3VlTHpWNVNuRm53S3dzCnZOR0gyWTVzams4SjdCZVpSMjdL + S2dqZTcvb3VtVE9JUWVlVU1QL1NaZ3MKLS0tIHdUZldWZWdIZ01VUWxLeEJDNmY0 + aEV2U1JMaTFYRldjc1kwNHczd3gvM1kKEytPjCdNTG+8SFnQxh50XKfjAxa1xn0t + D3dj6yMfIfkgnp84pI9PY5hBweHrEcdeUwhPrkNY8dRuiShv4o4xTQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-11T06:57:04Z" + mac: ENC[AES256_GCM,data:LKIihGyIcUImsmRWgPhWQRBeaFiXdWgaMwlif+FPNdmy/LSRlwIqIN8KzwuMu1zAlNvl1SVOVZL7SgRe9rZHax5pIn+Qrb5B+cuFPZTyvl24VBlJ+l29x182CKhRnT1RDDA9D7do+y8bG+rjyJ6u5d/yYcMAYIH9+I4fS4uERQw=,iv:23M4i1uCpQzfWZIp2c4gGThOCGotS3eajdjItlAwh2Y=,tag:MoD7LbWCu5EGxPeliRDinQ==,type:str] + encrypted_regex: ^(password|token|secret|key|privateKey|admin-password|db-password|passwordHash|tokenSigningKey)$ + version: 3.12.1 diff --git a/infra/gitea/values/secret-values.prod.enc.yaml b/infra/gitea/values/secret-values.prod.enc.yaml new file mode 100644 index 0000000..c8cfb6a --- /dev/null +++ b/infra/gitea/values/secret-values.prod.enc.yaml @@ -0,0 +1,27 @@ +# Gitea secrets for prod cluster +admin-password: ENC[AES256_GCM,data:4pXdFHPAXo9fnyEmAqDygucpGrOy,iv:Qa/fQvRoU8TXMlkSjlomwzOn0v1M/PJ606HZI+inRcQ=,tag:/fKGATm+rUSCUH+os12qlQ==,type:str] +db-password: ENC[AES256_GCM,data:lw3I+smG/1DaMFd2V98D7ENu6MB0g+e81A==,iv:DZmS4R2buArXMkO/Cjtp9gN9AqpTaVHs7NfqQFqciWY=,tag:OA9kzug/Mel6+GDlnYU/jA==,type:str] +sops: + age: + - recipient: age1xmnaqlrjzpk5hl7uhel9sehqh7zdz8p59qte2myt97aqd7lyeuxszuess7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCd2VUaHhQc0h4bmYwdmFy + WVJLS2dURWZnOUtCKzRoajB2RVI5U1ROOEVvCnV2VmxFTkhPNlErOE5SZzUyT0c1 + VitrWFlJVUt5N2plMitWVjZPUHBmYU0KLS0tIFJVUnBBZjl6cWlRYUNiZSs1V0Q2 + b1NBVnZydDVlY09LeHNpbkdsTzRNNmcKO9GFvLHIWTh/Aseuo3Z8FE47dE92MxJ6 + p5OCsZRw+bpQfURStiyckaoMW8Of716uDIS3v1JaW8u4xm3e+lZXGg== + -----END AGE ENCRYPTED FILE----- + - recipient: age16p0gwk8vt90vy2gm8jjca8rcyd2drv5526e997ukdelnv5ek8unqm0smuk + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBoOUZjdlk4MU4yWGNPOEs4 + ZkplUzlyV1lmQUxidHk3aDFhU1NOeElxeVU4CngxWS8vOTdUbEVNM2thMWgxNGRo + ZUlYdjVPTXFJWGtNWEJEa2V1dGhqSTgKLS0tIEI2V1hrWUVnRnovblhVQ2ROSENE + dXhwWXJJbnVBaFpraXJURERMR1lkUjQKFzaekfQFqg2cVT5gks4fXX26GtZu+M1F + g+pzNxpFVlzdrXiWrzjePshTVblVsxV8fKpUVoLYwwLOSILRzF3uwg== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-11T06:57:04Z" + mac: ENC[AES256_GCM,data:qWDAgi9DeHnc4TfH2la54mKtkNRkO3ArfXJBxZ6D6yEk5nylMA+Fw3FBmsKuU+F1/JN7CQVHbez37jjOXDmoFUfGXunionqkaf4wYz/3duRjdm/ApTLLMAYaq1YHzp6XNF4x+1LBtp0RadK//wwhxXQHoYdui9IH2Ts5ALLjOzo=,iv:B86+ovgnit5oKxY1wgxvYBEhRmnjJiQ7GdveJAGytfA=,tag:QgVjYIvIgwXvfbTxiti1OA==,type:str] + encrypted_regex: ^(password|token|secret|key|privateKey|admin-password|db-password|passwordHash|tokenSigningKey)$ + version: 3.12.1 diff --git a/infra/kargo-ci-pipeline/config.yaml b/infra/kargo-ci-pipeline/config.yaml new file mode 100644 index 0000000..fb2e059 --- /dev/null +++ b/infra/kargo-ci-pipeline/config.yaml @@ -0,0 +1,10 @@ +{ + "name": "kargo-ci-pipeline", + "namespace": "ci", + "step": "5", + "source": { + "repoURL": "https://github.com/Kargones/deploy-app-kargo-private.git", + "path": "kargo/ci", + "targetRevision": "main" + } +} diff --git a/infra/kargo-credentials/config.yaml b/infra/kargo-credentials/config.yaml new file mode 100644 index 0000000..16cfd71 --- /dev/null +++ b/infra/kargo-credentials/config.yaml @@ -0,0 +1,10 @@ +{ + "name": "kargo-credentials", + "namespace": "default", + "step": "5", + "source": { + "repoURL": "https://github.com/Kargones/deploy-app-kargo-private.git", + "path": "kargo/credentials", + "targetRevision": "main" + } +} diff --git a/infra/kargo-infra-pipeline/config.yaml b/infra/kargo-infra-pipeline/config.yaml new file mode 100644 index 0000000..f515bdd --- /dev/null +++ b/infra/kargo-infra-pipeline/config.yaml @@ -0,0 +1,10 @@ +{ + "name": "kargo-infra-pipeline", + "namespace": "infra", + "step": "5", + "source": { + "repoURL": "https://github.com/Kargones/deploy-app-kargo-private.git", + "path": "kargo/infra", + "targetRevision": "main" + } +} diff --git a/infra/kargo-test-env-pipeline/config.yaml b/infra/kargo-test-env-pipeline/config.yaml new file mode 100644 index 0000000..1a85bde --- /dev/null +++ b/infra/kargo-test-env-pipeline/config.yaml @@ -0,0 +1,10 @@ +{ + "name": "kargo-test-env-pipeline", + "namespace": "test-env", + "step": "5", + "source": { + "repoURL": "https://github.com/Kargones/deploy-app-kargo-private.git", + "path": "kargo/test-env", + "targetRevision": "main" + } +} diff --git a/infra/kargo/config.yaml b/infra/kargo/config.yaml new file mode 100644 index 0000000..ac9566c --- /dev/null +++ b/infra/kargo/config.yaml @@ -0,0 +1,14 @@ +{ + "name": "kargo", + "namespace": "kargo", + "step": "4", + "syncOptions": ["Replace=true"], + "source": { + "repoURL": "ghcr.io/akuity/kargo-charts", + "chart": "kargo", + "targetRevision": "1.9.5" + }, + "helm": { + "values": "api:\n service:\n type: ClusterIP\n adminAccount:\n enabled: true\n passwordHash: \"$2b$10$jk2IIBCWP.5mEzp30J0kkO1CyCXEBvCWzaPsUGVfsusvH0M2kl2aS\"\n tokenSigningKey: \"d76a6d38c725db844e799224ae2d0a2d38c0d31f5ca510aac44abc87c973b6e3\"\ncontroller:\n argocd:\n integrationEnabled: true\n namespace: argocd\n" + } +} diff --git a/infra/kargo/values/secret-values.dev.enc.yaml b/infra/kargo/values/secret-values.dev.enc.yaml new file mode 100644 index 0000000..6195ea0 --- /dev/null +++ b/infra/kargo/values/secret-values.dev.enc.yaml @@ -0,0 +1,27 @@ +# Kargo secrets for dev/test cluster +passwordHash: ENC[AES256_GCM,data:qmQr8l5EK92BZyadoAU0+hrOS2N8evnmxroL13GhQbD9idHKhHwkSt6fn1OgYyu+CtnJ6BxeyDyJCNbN,iv:4tnO8HczTo4GO+NFFQK6JRsOYXkS3wFiJfwYrCmot0M=,tag:LTeO8xl31f4+oLy/FDEyIQ==,type:str] +tokenSigningKey: ENC[AES256_GCM,data:Plf3vK+DJYmFsvS1cHTKtPvsvCC17i2/0lAEnG65CZVcrtux3+BiMY7rukLfW7uw/hQ+6JLB1PS4EWIGMNx/xw==,iv:54mdXGpgJ3f1dkeTyfZbfSoufJE89MUYIQpEz6jUt0E=,tag:KqK4shNvrQ7Dbu0+uYqjPw==,type:str] +sops: + age: + - recipient: age1xmnaqlrjzpk5hl7uhel9sehqh7zdz8p59qte2myt97aqd7lyeuxszuess7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwVHNjbmJ2K3ljSHNmdEpE + RzdrL1o5ZXhxQXl0N0ptWk5JWjlCYnVtTXdZCkRWUDl5RkkzYXFBbjRpMmdnY254 + YWhPeEw0MzF6K2VoTEI1R09PV0szQlkKLS0tIG42S0h4VUtsaWN0WTI0V1piYTU5 + MUYvbzVyWUVRZHRYd21MY2dWMzVBTE0KJ0cSonX/lD3PBjz3BFFPkea+XDDPqGAF + gd20j8xOjyV1nu6Dg1qq80ZN3E0rotXnTK5zu/AyW4wcByUTG465Hw== + -----END AGE ENCRYPTED FILE----- + - recipient: age1ame2tp44sq9rmkqzqvxy77eu7qd2035kmlgcsfjfxj2jughv3clqlku03g + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBUmlEM1Z4NDRZaU9LSFF3 + SjZnM0R6U0NlYWtkbGFMdGRXbW9YRjBIeVVjCk9nV05aZk04L0xvUnk4c3hRczZV + ZEY4dmI0NndjWHEvSDJ6OTUrS3owM3cKLS0tIFFhWUk5Qy9GMGNrWGM2WnY4SWNm + UVVUcktPakNYeWVxakp2RjQweG41MVEKoHKCkhsn29s4JuRCfBqoF78/UcShnCAx + sGnz9zTnE+LSVMbknG1+Y3kFdRNXesLFZfyyk3W2atjp7Tw9rGYWTw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-11T06:57:04Z" + mac: ENC[AES256_GCM,data:E4jKWJsO9bEMzEjmp+XhBx45heXB7W5op11YyC2TV2KA0PNfAa7eZXIAZ7PVjVIfhbmODv3pd3KG4mY7lJ9I1ly6VfFGl4wMtXZkQlVt5+2DF6GyLGGfjKftRcGni4xP2J4wfzZGiIiQ2G8IUfmGy8Wpegw9lo6/UvES1w1kies=,iv:6fwg2NNoZnKq9jiFHLRQ6FZXrx9OzFEnxWU1VwEVoj0=,tag:CiJAekk+4dp/pyWkqXJKVw==,type:str] + encrypted_regex: ^(password|token|secret|key|privateKey|admin-password|db-password|passwordHash|tokenSigningKey)$ + version: 3.12.1 diff --git a/infra/kargo/values/secret-values.prod.enc.yaml b/infra/kargo/values/secret-values.prod.enc.yaml new file mode 100644 index 0000000..579341e --- /dev/null +++ b/infra/kargo/values/secret-values.prod.enc.yaml @@ -0,0 +1,27 @@ +# Kargo secrets for prod cluster +passwordHash: ENC[AES256_GCM,data:iYRGwF7yug4fy4q70CoWMJCAIwd5nszzTqXHXe88zGRRYw6YtvAszCpGcecRRFhCwIfycTnciXfN,iv:CwerCu5GfMhpTpeqQ2QmMBMwxf7t2L12PUM4yCT4yIE=,tag:XNhTKS0d6T0VhK6E9BDn1w==,type:str] +tokenSigningKey: ENC[AES256_GCM,data:+05VkEeKatxayA1wK0a19fE6PFc3utOHvvT3Z+4KwfUBI778n5X9rMwSQQSFsbQyduPLITGf5VYKGaC5z3okAQ==,iv:uuS6oHdCLrvh6H38sfYzXTsrZ1lw5CJxjNN/0jchV9Q=,tag:iVuTqL2zew18OMeFwnGqrQ==,type:str] +sops: + age: + - recipient: age1xmnaqlrjzpk5hl7uhel9sehqh7zdz8p59qte2myt97aqd7lyeuxszuess7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBEYytrSWhtUWtEQUpQVEhh + S1RvN2N3ZFcvaFVmdU5KQ2pYTitPMUJJQTNFCml4YWMzRWdiZHAxRUoycHRmTU1L + RUhDOEJzSThIVDV0Y1RSQWczeEVXU0UKLS0tIHgwM0k3R2k1V1h5U2tWajdnMElj + SUdhZzh1S3Y3cktwTUJzQk5Lc3BjeTAK4LOXLhfyd4NMWsuUm0/Bjxq+9ni6wntw + 6u2UgYliecKNw4IX+2Ukhp/z4jGlVEayAE8QrfCj7RjBATPUYncPEw== + -----END AGE ENCRYPTED FILE----- + - recipient: age16p0gwk8vt90vy2gm8jjca8rcyd2drv5526e997ukdelnv5ek8unqm0smuk + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1bittd3daOE9jWUJKeHB4 + R2k4Q3lNSzNkTDA0RTZlL1JrSFNMalRhWEVVCjNYSDVZU3kvRHlqZTRaOGRkZDJI + RUJiM2RMY0tFU2QvT25tQlFtK1l1NTgKLS0tIGJDYzhFelR1TkpNL2JmMGJ4YXd2 + SGNGTGhGWGovbUJHMHh0QWhIWlhBdVUKAKxeFgOPJRaTl5z0bydzd1nr5SDmqfMx + 7n/OjVadcCg4PLd54eMpgiJ7ts4UeaAK+RxdHtI9Y7jP1ConLffoAg== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-11T06:57:04Z" + mac: ENC[AES256_GCM,data:Mp01K4uHW7ZFXzURs8nzkfwe6d7xgiOds12/VN1I5qB5OoC3afM1pZRQ7/mM0lTyueVt9hTh4B76zAFp6rB+/ombjJ5JPnwyEayAklovy7R6BFC1podhb78npC2u7K5P7DIFI54nJqj1XfFt4eIMQjkR6AnFeT1pqzquF7SVnLQ=,iv:VesrzDd09vugtzAYjB/oyHm99Dmm8dlDgP0NITvd4Rs=,tag:5z5zBC/7ulnqTRz9UXyrhw==,type:str] + encrypted_regex: ^(password|token|secret|key|privateKey|admin-password|db-password|passwordHash|tokenSigningKey)$ + version: 3.12.1 diff --git a/infra/traefik-routes/config.yaml b/infra/traefik-routes/config.yaml new file mode 100644 index 0000000..fde26b0 --- /dev/null +++ b/infra/traefik-routes/config.yaml @@ -0,0 +1,10 @@ +{ + "name": "traefik-routes", + "namespace": "kube-system", + "step": "3", + "source": { + "repoURL": "https://github.com/Kargones/deploy-app-kargo-private.git", + "path": "infra/traefik-routes/manifests", + "targetRevision": "main" + } +} diff --git a/infra/traefik-routes/manifests/gitea-ingress.yaml b/infra/traefik-routes/manifests/gitea-ingress.yaml new file mode 100644 index 0000000..26efecd --- /dev/null +++ b/infra/traefik-routes/manifests/gitea-ingress.yaml @@ -0,0 +1,41 @@ +# Gitea HTTPS IngressRoute via Traefik +# Uses default TLS store (wildcard-tls from kube-system via TLSStore) +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: gitea-https + namespace: gitea +spec: + entryPoints: + - websecure + routes: + - match: HostRegexp(`gitea.k3s\..+\.local`) + kind: Rule + middlewares: + - name: sslheader + namespace: kube-system + - name: gitea-buffer-timeout + namespace: gitea + services: + - name: gitea-http + port: 3000 + tls: {} +--- +# HTTP → HTTPS redirect for Gitea +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: gitea-http-redirect + namespace: gitea +spec: + entryPoints: + - web + routes: + - match: HostRegexp(`gitea.k3s\..+\.local`) + kind: Rule + middlewares: + - name: redirect-https + namespace: kube-system + services: + - name: gitea-http + port: 3000 diff --git a/infra/traefik-routes/manifests/gitea-ssh.yaml b/infra/traefik-routes/manifests/gitea-ssh.yaml new file mode 100644 index 0000000..09938da --- /dev/null +++ b/infra/traefik-routes/manifests/gitea-ssh.yaml @@ -0,0 +1,14 @@ +# Gitea SSH access via Traefik TCP routing (port 2222) +apiVersion: traefik.io/v1alpha1 +kind: IngressRouteTCP +metadata: + name: gitea-ssh + namespace: gitea +spec: + entryPoints: + - ssh + routes: + - match: HostSNI(`*`) + services: + - name: gitea-ssh + port: 22 diff --git a/infra/traefik-routes/manifests/kargo-ingress.yaml b/infra/traefik-routes/manifests/kargo-ingress.yaml new file mode 100644 index 0000000..dfdcc54 --- /dev/null +++ b/infra/traefik-routes/manifests/kargo-ingress.yaml @@ -0,0 +1,21 @@ +# Kargo dashboard HTTPS IngressRoute +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: kargo-https + namespace: kargo +spec: + entryPoints: + - websecure + routes: + - match: HostRegexp(`kargo.k3s\..+\.local`) + kind: Rule + middlewares: + - name: kargo-tls-middleware + namespace: kargo + services: + - name: kargo-api + port: 443 + scheme: https + serversTransport: kargo-skip-verify + tls: {} diff --git a/infra/traefik-routes/manifests/kargo-transport.yaml b/infra/traefik-routes/manifests/kargo-transport.yaml new file mode 100644 index 0000000..9a257a8 --- /dev/null +++ b/infra/traefik-routes/manifests/kargo-transport.yaml @@ -0,0 +1,8 @@ +# ServersTransport to skip TLS verification for Kargo backend (self-signed cert) +apiVersion: traefik.io/v1alpha1 +kind: ServersTransport +metadata: + name: kargo-skip-verify + namespace: kargo +spec: + insecureSkipVerify: true diff --git a/infra/traefik-routes/manifests/middlewares.yaml b/infra/traefik-routes/manifests/middlewares.yaml new file mode 100644 index 0000000..ab002d7 --- /dev/null +++ b/infra/traefik-routes/manifests/middlewares.yaml @@ -0,0 +1,57 @@ +# HTTP → HTTPS redirect +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: redirect-https + namespace: kube-system +spec: + redirectScheme: + scheme: https + permanent: true +--- +# Forward X-Forwarded-Proto header for backends behind TLS termination +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: sslheader + namespace: kube-system +spec: + headers: + customRequestHeaders: + X-Forwarded-Proto: "https" +--- +# Gitea: buffer large requests (git push) + timeout for CI builds +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: gitea-buffer-timeout + namespace: gitea +spec: + buffering: + maxRequestBodyBytes: 0 + maxResponseBodyBytes: 0 + memRequestBodyBytes: 20971520 + memResponseBodyBytes: 20971520 + retryExpression: "IsNetworkError()" +--- +# ArgoCD: X-Forwarded-Proto for TLS termination +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: argocd-tls-middleware + namespace: argocd +spec: + headers: + customRequestHeaders: + X-Forwarded-Proto: "https" +--- +# Kargo: X-Forwarded-Proto for TLS termination +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: kargo-tls-middleware + namespace: kargo +spec: + headers: + customRequestHeaders: + X-Forwarded-Proto: "https" diff --git a/infra/traefik-routes/manifests/namespaces.yaml b/infra/traefik-routes/manifests/namespaces.yaml new file mode 100644 index 0000000..5dea267 --- /dev/null +++ b/infra/traefik-routes/manifests/namespaces.yaml @@ -0,0 +1,14 @@ +# Ensure namespaces exist for cross-namespace middleware references +apiVersion: v1 +kind: Namespace +metadata: + name: gitea + labels: + name: gitea +--- +apiVersion: v1 +kind: Namespace +metadata: + name: kargo + labels: + name: kargo diff --git a/infra/traefik-routes/manifests/tls-store.yaml b/infra/traefik-routes/manifests/tls-store.yaml new file mode 100644 index 0000000..392297f --- /dev/null +++ b/infra/traefik-routes/manifests/tls-store.yaml @@ -0,0 +1,10 @@ +# Default TLS store — uses wildcard-tls from kube-system as default cert. +# All IngressRoutes with tls: {} will use this certificate. +apiVersion: traefik.io/v1alpha1 +kind: TLSStore +metadata: + name: default + namespace: kube-system +spec: + defaultCertificate: + secretName: wildcard-tls diff --git a/infra/traefik-routes/manifests/traefik-dashboard.yaml b/infra/traefik-routes/manifests/traefik-dashboard.yaml new file mode 100644 index 0000000..096c7b7 --- /dev/null +++ b/infra/traefik-routes/manifests/traefik-dashboard.yaml @@ -0,0 +1,19 @@ +# Traefik Dashboard IngressRoute +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: traefik-dashboard + namespace: kube-system +spec: + entryPoints: + - websecure + routes: + - match: HostRegexp(`traefik.k3s\..+\.local`) && (PathPrefix(`/dashboard`) || PathPrefix(`/api`)) + kind: Rule + middlewares: + - name: sslheader + namespace: kube-system + services: + - name: api@internal + kind: TraefikService + tls: {} diff --git a/kargo/ci/kustomization.yaml b/kargo/ci/kustomization.yaml new file mode 100644 index 0000000..72eead1 --- /dev/null +++ b/kargo/ci/kustomization.yaml @@ -0,0 +1,9 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - namespace.yaml + - project.yaml + - warehouse.yaml + - stages/dev.yaml + - stages/prod.yaml + - verification/runner-health.yaml diff --git a/kargo/ci/namespace.yaml b/kargo/ci/namespace.yaml new file mode 100644 index 0000000..6ffed51 --- /dev/null +++ b/kargo/ci/namespace.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: ci + labels: + kargo.akuity.io/project: "true" diff --git a/kargo/ci/project.yaml b/kargo/ci/project.yaml new file mode 100644 index 0000000..cfd8b3b --- /dev/null +++ b/kargo/ci/project.yaml @@ -0,0 +1,16 @@ +apiVersion: kargo.akuity.io/v1alpha1 +kind: Project +metadata: + name: ci +--- +apiVersion: kargo.akuity.io/v1alpha1 +kind: ProjectConfig +metadata: + name: ci + namespace: ci +spec: + promotionPolicies: + - stageSelector: { name: dev } + autoPromotionEnabled: true + - stageSelector: { name: prod } + autoPromotionEnabled: true diff --git a/kargo/ci/stages/dev.yaml b/kargo/ci/stages/dev.yaml new file mode 100644 index 0000000..a019645 --- /dev/null +++ b/kargo/ci/stages/dev.yaml @@ -0,0 +1,54 @@ +apiVersion: kargo.akuity.io/v1alpha1 +kind: Stage +metadata: + name: dev + namespace: ci +spec: + requestedFreight: + - origin: + kind: Warehouse + name: ci-images + sources: + direct: true + promotionTemplate: + spec: + vars: + - name: gitopsRepo + value: https://github.com/Kargones/deploy-app-kargo-private.git + - name: targetBranch + value: ci/stage/${{ ctx.stage }} + steps: + - uses: git-clone + config: + repoURL: ${{ vars.gitopsRepo }} + checkout: + - branch: main + path: ./src + - branch: ${{ vars.targetBranch }} + create: true + path: ./out + - uses: git-clear + config: + path: ./out + - uses: copy + config: + inPath: ./src/ci + outPath: ./out/ci + - uses: yaml-update + config: + path: ./out/ci/gitea-runner/manifests/runner.yaml + updates: + - key: spec.template.spec.containers.0.image + value: gitea/act_runner:${{ imageFrom("gitea/act_runner").Tag }} + - uses: git-commit + as: commit + config: + path: ./out + message: "promote(ci/${{ ctx.stage }}): act_runner ${{ imageFrom(\"gitea/act_runner\").Tag }}" + - uses: git-push + config: + path: ./out + targetBranch: ${{ vars.targetBranch }} + verification: + analysisTemplates: + - name: runner-health diff --git a/kargo/ci/stages/prod.yaml b/kargo/ci/stages/prod.yaml new file mode 100644 index 0000000..3804767 --- /dev/null +++ b/kargo/ci/stages/prod.yaml @@ -0,0 +1,64 @@ +apiVersion: kargo.akuity.io/v1alpha1 +kind: Stage +metadata: + name: prod + namespace: ci +spec: + requestedFreight: + - origin: + kind: Warehouse + name: ci-images + sources: + stages: + - dev + promotionTemplate: + spec: + vars: + - name: gitopsRepo + value: https://github.com/Kargones/deploy-app-kargo-private.git + - name: sourceBranch + value: ci/stage/dev + - name: targetBranch + value: ci/stage/prod + steps: + - uses: git-clone + config: + repoURL: ${{ vars.gitopsRepo }} + checkout: + - branch: ${{ vars.sourceBranch }} + path: ./src + - branch: ${{ vars.targetBranch }} + create: true + path: ./out + - uses: git-clear + config: + path: ./out + - uses: copy + config: + inPath: ./src/ci + outPath: ./out/ci + - uses: git-commit + as: commit + config: + path: ./out + message: "promote(ci/prod): act_runner ${{ imageFrom(\"gitea/act_runner\").Tag }}" + - uses: git-push + as: push + config: + path: ./out + generateTargetBranch: true + - uses: git-open-pr + as: open-pr + config: + repoURL: ${{ vars.gitopsRepo }} + sourceBranch: ${{ outputs.push.branch }} + targetBranch: ${{ vars.targetBranch }} + createTargetBranch: true + title: "promote(ci/prod): act_runner ${{ imageFrom(\"gitea/act_runner\").Tag }}" + description: | + ## Kargo Promotion — CI + **Image:** gitea/act_runner:${{ imageFrom("gitea/act_runner").Tag }} + - uses: git-wait-for-pr + config: + repoURL: ${{ vars.gitopsRepo }} + prNumber: ${{ outputs['open-pr'].pr.id }} diff --git a/kargo/ci/verification/runner-health.yaml b/kargo/ci/verification/runner-health.yaml new file mode 100644 index 0000000..b77ba92 --- /dev/null +++ b/kargo/ci/verification/runner-health.yaml @@ -0,0 +1,25 @@ +apiVersion: argoproj.io/v1alpha1 +kind: AnalysisTemplate +metadata: + name: runner-health + namespace: ci +spec: + metrics: + - name: runner-deployment-exists + provider: + job: + spec: + backoffLimit: 0 + template: + spec: + serviceAccountName: kargo-verifier + restartPolicy: Never + containers: + - name: check + image: alpine/k8s:1.35.1 + command: ["/bin/sh", "-c"] + args: + - | + echo "Checking gitea-runner deployment..." + kubectl get deployment gitea-runner -n gitea-runner -o jsonpath='{.metadata.name}' && echo " exists" || exit 1 + echo "Runner health check passed" diff --git a/kargo/ci/warehouse.yaml b/kargo/ci/warehouse.yaml new file mode 100644 index 0000000..56807c0 --- /dev/null +++ b/kargo/ci/warehouse.yaml @@ -0,0 +1,11 @@ +apiVersion: kargo.akuity.io/v1alpha1 +kind: Warehouse +metadata: + name: ci-images + namespace: ci +spec: + subscriptions: + - image: + repoURL: gitea/act_runner + semverConstraint: ">=0.2.0" + discoveryLimit: 5 diff --git a/kargo/credentials/git-creds-ci.dev.enc.yaml b/kargo/credentials/git-creds-ci.dev.enc.yaml new file mode 100644 index 0000000..94d3d7a --- /dev/null +++ b/kargo/credentials/git-creds-ci.dev.enc.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +kind: Secret +metadata: + name: github-creds + namespace: ci + labels: + kargo.akuity.io/cred-type: git +type: Opaque +stringData: + repoURL: https://github.com/Kargones/deploy-app-kargo-private.git + username: Kargones + password: ENC[AES256_GCM,data:m9CZFhTHwaX6TrpGtbAynbI7eiprSrhCVVtST6fWiduFP55/EWtx1Q==,iv:iAjeVVakD8SZWhaEBu7JVR1YL2UGzYNBoy1W13M+Jwg=,tag:ABSswqyDhJG8+zlu8dWrgg==,type:str] +sops: + age: + - recipient: age1xmnaqlrjzpk5hl7uhel9sehqh7zdz8p59qte2myt97aqd7lyeuxszuess7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHOWI4eWZxOERjRHVhV1VI + MVE3WDErejZrNzBaRnVHK280dXI4WThxR2tvCmVzbE1HR1MzcEgybm8vUVVSOWJY + VlVvREl4NVRDRElHVHk5aWpnVkVhNW8KLS0tIG5FOXRwRy8xakFvaVlBTXF5OXJJ + aHFlbWh0Ym1NWEswbFM5N01JRGtGMUUKyjiN+bK0+6PLc/LG/dozgrAhB4PLcZmV + JVtxrSZWV6RQOuvc/HUw2yhO3dJldYqWauX+7ZOy2o1JACdPe9ixdQ== + -----END AGE ENCRYPTED FILE----- + - recipient: age1ame2tp44sq9rmkqzqvxy77eu7qd2035kmlgcsfjfxj2jughv3clqlku03g + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHWU9JLzdwbDI1SDJ3MnlE + YnlRQkdzWExpa1FGNjArSHFCamc2bWJnbjBBCnlkQlVEQVNDTXMvZ3NWRzhyT2lM + R0FpVUdleUVUcVVrTnRxQjVnSFo3S2cKLS0tIG1MZ0hYdGJpdTJ3WWU3MU1WeWFr + cklvSldLdW5ERDF1aW95dDlxOUtGbDAK7uoTP8idcEM8rQ7rRashsbzc9f4S7qI9 + Bl87wLgMAFYfFO41cwSqhMY+gr7HRkDQq65CWo8HpQjMMlneC72jVQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-11T06:58:02Z" + mac: ENC[AES256_GCM,data:OYJAnGhgB0sOC2KEgse7ZYMkrvrRNsMWqVQZM29VbhPbvp3s3GMmJPROPydsjvm6OE4EIi0C6ry2h9pGoRY5IApw6+tSXVmrlr3oQIjkGqimJVdJ0oBSwEYtZ6gNKpsn1I7ZthXCHBfZmmESkYiTJj8ogdXxNLIqydIuITengpI=,iv:IpBxWcDeGUD9ucIAVjY3Ojc0wd63nWDPDIcH8OtvJY8=,tag:yDZ8d9E9dufB/iGTk71t2Q==,type:str] + encrypted_regex: ^(password|token|secret|key|privateKey|admin-password|db-password|passwordHash|tokenSigningKey)$ + version: 3.12.1 diff --git a/kargo/credentials/git-creds-ci.prod.enc.yaml b/kargo/credentials/git-creds-ci.prod.enc.yaml new file mode 100644 index 0000000..cb00b75 --- /dev/null +++ b/kargo/credentials/git-creds-ci.prod.enc.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +kind: Secret +metadata: + name: github-creds + namespace: ci + labels: + kargo.akuity.io/cred-type: git +type: Opaque +stringData: + repoURL: https://github.com/Kargones/deploy-app-kargo-private.git + username: Kargones + password: ENC[AES256_GCM,data:OHHKJ82Bh3UtuWJwtIr4dNnMDxweZEs/bHQQ7buy+zQM99f1SC4zEA==,iv:kn2P/KO5QKYhNxWKcbphmEmeJayWz/xA3NbfSq3T8K4=,tag:EzwiJHrK36SqRgISnzYmmw==,type:str] +sops: + age: + - recipient: age1xmnaqlrjzpk5hl7uhel9sehqh7zdz8p59qte2myt97aqd7lyeuxszuess7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnREI0NnE1Z0Z6ZE1HWG4x + aHhZeDBIYmNJNjZJbVNJR2Myb3Zyb092cW1NCkt0T3Rwamx0S1dudE1rM1ZCTDZv + ZDlJTmh5YjdUT3k1YlZlM2FOdzgrc3MKLS0tIFhNeFdrNkRBelZRUldqenhBVFAx + dHF0cUFmNXRHS3RkeTVVQzhIVTBXdm8K6c/K14oe/bPkaFCJi/OpoLj3q8RE20Hn + /1yeNCfRNkAPyOYQae6XgPI2xL5H+PfhMzRWYa6ebI/Pefl3n4WeSA== + -----END AGE ENCRYPTED FILE----- + - recipient: age16p0gwk8vt90vy2gm8jjca8rcyd2drv5526e997ukdelnv5ek8unqm0smuk + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBdFhPTWRZUEllR01sQzBM + RTQvbzM5ZnoyaEtHS21hS1BCWjJFNkZDZml3ClBPZHgvU2lCTHRwL01JUFRpY3pI + RTcvNkNZNXkwYkRVQzBWNVRuSllPcTAKLS0tIDMwTlFkcXR1QmNBNDVwQXdPUzR0 + UlBIbE83UXEzcmVNWXhyOWRXUit4REUKxJQwLz/w4BGMW6OggbaG0kDv0CWIUQi6 + H1gWD4HKT1JM8rI9GrBJRijmQhJvfn+s3PcRnimVa8sFUXJwR8ffrA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-11T06:58:02Z" + mac: ENC[AES256_GCM,data:0sm3v9oBiyy+3/es2piC9O3505QyaiylQSy7/7IkOYHcLQi5T0R6pXV+LlTMrJgxbvQg5PjyFxtGDF/MS9VM7iimDwJzAwC+Jv9Z9senKG6DwenUl8B/hHtXoWHGIxKrzR+0nnh756u+ftDTR5u7PDdd03UIn+n6fhpZ3tRB1q8=,iv:T3KPpdXz+8Bq0TBlIPR3+tFWHEBsE515rBWWDyM0VGM=,tag:+aBXzSUykrdazF6lXGNwHQ==,type:str] + encrypted_regex: ^(password|token|secret|key|privateKey|admin-password|db-password|passwordHash|tokenSigningKey)$ + version: 3.12.1 diff --git a/kargo/credentials/git-creds-infra.dev.enc.yaml b/kargo/credentials/git-creds-infra.dev.enc.yaml new file mode 100644 index 0000000..3ce833e --- /dev/null +++ b/kargo/credentials/git-creds-infra.dev.enc.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +kind: Secret +metadata: + name: github-creds + namespace: infra + labels: + kargo.akuity.io/cred-type: git +type: Opaque +stringData: + repoURL: https://github.com/Kargones/deploy-app-kargo-private.git + username: Kargones + password: ENC[AES256_GCM,data:lzaZLTkmA68DadpquacJNc6CMxwv3wOlWh6Ze8e23F9lzFKw3oB5gg==,iv:9EZUg6DSUFnNddOaiB2oIfNYhaOKKkrP9Hkf+5OGcLk=,tag:rr6ej2x87mquQbXiBM7+Ow==,type:str] +sops: + age: + - recipient: age1xmnaqlrjzpk5hl7uhel9sehqh7zdz8p59qte2myt97aqd7lyeuxszuess7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCeGdkaVJiNWE0Q0xWbTVT + dkZDN296VXJUMktMVUZ2U3FyeUwvVzBSaWc0CmRlWFpLdTlCNXl3eEtKcDRrUzhV + SG9KdkhlSTg0SnZwK3BvS0hkT3FjbjgKLS0tIDA2Y1lic053ejR0UWZUekZ1Y1JK + c2llUmhKNTRjaW1zQ3AyZzUvR1VRUG8KuFXq5pbpEEZd3P/E5bD0FCuSOIuGCsJL + bUx6VucI1zZF0DbXjzr28FsxqSJW4GiCpDscj1LGQIZa5jvj8aWMXA== + -----END AGE ENCRYPTED FILE----- + - recipient: age1ame2tp44sq9rmkqzqvxy77eu7qd2035kmlgcsfjfxj2jughv3clqlku03g + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRRlh5SXdkTmZOVUdXc21N + aXNZaDhydXA3dUU4OHlidmViM2xUQU5rNDF3Ck9iditWSWcyaWoxNTVTRzN5Y0ZU + c21BT2R6U2lxNkh6cU9kdjFSRUVjUWsKLS0tIHBwWGI1R2p0TTg1amFRM2FlYVQx + Q2lIZDJ0ZkliWEtiVGd5eXIxMjB1OGMKeK2iTyPBrcIWByU9QXZ3Ora7gylwC66g + diGbcUF5ER7mUt0KEILTwuMkTUbhy1F5zLYB7p4e49YdY2O8mz51SA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-11T06:58:02Z" + mac: ENC[AES256_GCM,data:dzyW+dAsjPDrZQ3EWNnhLWfd9DSmRVSp1Qrm+nx4qFfsRoS5y61jnkhVyupq2OUVsuUTuePIAqmZQI16HD0TTMJIN9UKPdW2sEj/DGwdBXqcJRs6mvJlv79Jh2VlzJdJSpZf/YhCBVIVThZqrWBI1T1jPdN1gaJ0ov6cSAqYjPU=,iv:MMhdUthu2nUFJOkxXz00xXMiH7tit7sNejU/aXuQOmY=,tag:+NSHR9T4wlpJaBH5ZdxhvA==,type:str] + encrypted_regex: ^(password|token|secret|key|privateKey|admin-password|db-password|passwordHash|tokenSigningKey)$ + version: 3.12.1 diff --git a/kargo/credentials/git-creds-infra.prod.enc.yaml b/kargo/credentials/git-creds-infra.prod.enc.yaml new file mode 100644 index 0000000..e2651ea --- /dev/null +++ b/kargo/credentials/git-creds-infra.prod.enc.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +kind: Secret +metadata: + name: github-creds + namespace: infra + labels: + kargo.akuity.io/cred-type: git +type: Opaque +stringData: + repoURL: https://github.com/Kargones/deploy-app-kargo-private.git + username: Kargones + password: ENC[AES256_GCM,data:2ucqkKTdxBlW2GCRmr4ZqrZZS2KuIcUCkhyF6/dIy0jGiUTM1iQIiQ==,iv:gTnztDCoZX9rfK6cnnoOOs6WD8mmw6tWr2z9JUkj+sA=,tag:I5OgSmjtAbnXxyhCe7y3GA==,type:str] +sops: + age: + - recipient: age1xmnaqlrjzpk5hl7uhel9sehqh7zdz8p59qte2myt97aqd7lyeuxszuess7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0RVRoa2ZTT2llSitDYlRn + RU1RRkVNdnFFZWpMU0ZoU2Q0bGRKVFViZEc4CkdaalppTll1Q0c4T29aYks2a3Nq + azBaMWtJL3hyQlFVMFpUTjcrQ3BkU0kKLS0tIC80azJYWnhGZHpwK0lWa1FrS1d4 + WlFjQk9WZVdoSnhnT1lROFZzUWMxb00KJ6i6Vap1FCYYUcTiNh5dyHbSeyXthtdf + iQcMjvZlOgKuHVPmaiXv8Mh+AHNl0RgWN2nNEoa1NPhriGU36ZmVWA== + -----END AGE ENCRYPTED FILE----- + - recipient: age16p0gwk8vt90vy2gm8jjca8rcyd2drv5526e997ukdelnv5ek8unqm0smuk + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzMUx5UkNBZHlZdVhlaXV3 + OVNXTitPd2lQQXFoanNjb014ODB3ZUVLRHlvCmdBbkpmaXkzSXZxRFdPZEVubVJC + NHpyUDVkVjV5QXRPbnBHNkZhclMzc1UKLS0tIGtWcHZGMEorbFNEeStmSW80WE9N + RjRLYkhHMmd6UTNUSkxCUUFvMzVkdTAKJhUHz7PDrJca3OIdXyzXzD86/7tkCSm4 + Q6q6WbscBBMtclrO5EfbHuzUUNuejFRLjeHjvPCBb5z/i6sp6Pxyuw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-11T06:58:02Z" + mac: ENC[AES256_GCM,data:KetBMvqfuE4eSrQoKmFJ0fkHHAvxFjQJvm9b9haSODfXDUxZ7DOYlVAVrZzf7L9VYFj7iP+yQeW2cLuV0JRH9+CL6u2GuvtK5WPC82NhRK/I5dEF+x3VIFjc3amr62FEuOjPeLOiAqluPeJ3BscW/Gj6UXKrLgrPzmZZgzzBHb4=,iv:fNbOFcpkAmom0Tf7xeoDfyklWNxIhHANS3WguPtrDK4=,tag:lsbhvAgSWdp+XKPKpGU56Q==,type:str] + encrypted_regex: ^(password|token|secret|key|privateKey|admin-password|db-password|passwordHash|tokenSigningKey)$ + version: 3.12.1 diff --git a/kargo/credentials/git-creds-test-env.dev.enc.yaml b/kargo/credentials/git-creds-test-env.dev.enc.yaml new file mode 100644 index 0000000..9e325df --- /dev/null +++ b/kargo/credentials/git-creds-test-env.dev.enc.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +kind: Secret +metadata: + name: github-creds + namespace: test-env + labels: + kargo.akuity.io/cred-type: git +type: Opaque +stringData: + repoURL: https://github.com/Kargones/deploy-app-kargo-private.git + username: Kargones + password: ENC[AES256_GCM,data:pGwKoR6eurha3ATmL0XP01DTK3qXCxAV3SdFYmNFokKMZI+VuzZ/GQ==,iv:DKVdeBRQS+HjPkHftJZZuXf7yB+I18Ae3iK+7L+hZQ0=,tag:/K6twgUKTNrn6s1rDTAeQA==,type:str] +sops: + age: + - recipient: age1xmnaqlrjzpk5hl7uhel9sehqh7zdz8p59qte2myt97aqd7lyeuxszuess7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYTk5seDNiR2dRcXRRclJZ + UlNuRXZGd3ZMTDNsaHVrYUtnUmsyNk1IVkJFCmo0Y0pwdnlsay9qcy8rakk4ejBF + VHAzbmRObUFVVVpZN0JraHRlVmhhNW8KLS0tIHNXd01OUnVxclRXcE9iNFNzZS9S + UlQzRnlSb2F0Y0J0eVdZN1BSelRrSWcK8V99m3Hh2mOm9csGG42k4FIeFbQnkXIr + w3elSENAib0rFz7Uewpn1VD3yjFL7SVv33bVOEuM3KlHDtUnF6fuuQ== + -----END AGE ENCRYPTED FILE----- + - recipient: age1ame2tp44sq9rmkqzqvxy77eu7qd2035kmlgcsfjfxj2jughv3clqlku03g + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOS05ZanNzMWRFRG5EUlNq + WmtLUHpHRE0rWXRuVXRLRDFiRDZSZmdEc2lnCmMrbHRxRUhIWDFkaTJlekxrckxj + V3ROU25aOVZGVzVUY3IwRlhwYWhBWEUKLS0tIHZCS1ZobFlqQ2NZSUt3N1VSV2l4 + SmVWWDRhckRxek1jRFpPUnIxb0QxaDQKmkVXDqP0tjaWo/fkdqrIatV/bhyQt9vb + Rzz21KATjKow6VtekA3FVOVchlDsaYDLkhuLI69I1lIYqR99ovS+8w== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-11T06:58:02Z" + mac: ENC[AES256_GCM,data:CDESJXzhctA4WexUb2hP6ykWkRCWUsgIYHOSmRnHUlyf6Pd8uF43Bl/+ZHWhE6SLWf3LKGMOKSU60Qkh1aSH+Z9BqaiKa3dL0MIQx4yXRe9NzS/mEki4IsuQi27AZ6BKD93tznyVKbCAzxmyP1jRhbRNIKBA2dWoQAITX1w2vvA=,iv:l8JZK3a17DfIn3llapKnUZH7SRNCte5MNPZzjtPJbxA=,tag:rEcarIr7UhsV+THixTUiKw==,type:str] + encrypted_regex: ^(password|token|secret|key|privateKey|admin-password|db-password|passwordHash|tokenSigningKey)$ + version: 3.12.1 diff --git a/kargo/credentials/git-creds-test-env.prod.enc.yaml b/kargo/credentials/git-creds-test-env.prod.enc.yaml new file mode 100644 index 0000000..9648671 --- /dev/null +++ b/kargo/credentials/git-creds-test-env.prod.enc.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +kind: Secret +metadata: + name: github-creds + namespace: test-env + labels: + kargo.akuity.io/cred-type: git +type: Opaque +stringData: + repoURL: https://github.com/Kargones/deploy-app-kargo-private.git + username: Kargones + password: ENC[AES256_GCM,data:YIFtzQT8BYFwj5SfRDGxd/ND6BzpFSbERF3u+TyFjCoFqQXqk4g9ew==,iv:gOwNFYoErJhEJglBP9Oed45/CFQXXHlPqid3RzScvdA=,tag:iTJfhSTKceOl5lv4YiGo4Q==,type:str] +sops: + age: + - recipient: age1xmnaqlrjzpk5hl7uhel9sehqh7zdz8p59qte2myt97aqd7lyeuxszuess7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBza2JKZTlxSTZOZ1lzNllu + TWdoL0lKSDc0Ri9BMWs1aDhSU1VaQ1dod2dzCk5sRHdIa1B3a2RMbTViZ3lPc04y + OUQ4WVNRR3JrZ1lyZXJvd3lFVUYxdlEKLS0tIFRNM0dqR1RGMVZ2alprMmxRQndo + Y0h3RE5WaHprRDZWUnBCQURhS0tnbHMKz9/qP2w1KURlDAWVcjfUFz1kJy/ed53w + SpKMwvWTfYTvvZMNnz1XgxMfKXu4TKWAuP9mJ+rmcj5jIcPSGxetUA== + -----END AGE ENCRYPTED FILE----- + - recipient: age16p0gwk8vt90vy2gm8jjca8rcyd2drv5526e997ukdelnv5ek8unqm0smuk + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYeTd6Uk5yN2o5MDhsa0V6 + UTZGZ29rSmFYbm5uRkg2UGNNdW13UmJ0eWxFCnZCWU5RalJEdFQ1SCtxdGQxVDhV + R3FsbkppRHkwbEdmYTU0dE5leEUxN2cKLS0tIDZtc3orbkhKMVVmdnpQRDVRUm9P + ck5QYkczblV0YndpQ0hoN3lDWDhrbUEKG5nPWrnAHFvUCsf/Zwgo22oiP1nIvXc5 + PSo+hPCzFAjVtg7y1jO8HcwUVOgtcH/LN4NwcMF/I7VZajHRZXEQXQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-11T06:58:02Z" + mac: ENC[AES256_GCM,data:3/YKxY5Ai543PDiUZi767xsmgJSI+bWyBQER+ICo9jQydbef1gJ2Rp3TitnuSiD2H+l41b2tIEFp4y3IaXSD6B+8cbf+bs7YdXznJzFd/V3FKjKncQJkJdTlLDijJRsjPczEFA/syhy/i8jMORoid1SNQrk2l0XmiWx7bujTOys=,iv:Wtdf3swbTJEXQu2+JNu8mqYHWvK9DIZRLuXLoKB5n9w=,tag:jMiSS9gzmZpWXNVq3liyTA==,type:str] + encrypted_regex: ^(password|token|secret|key|privateKey|admin-password|db-password|passwordHash|tokenSigningKey)$ + version: 3.12.1 diff --git a/kargo/credentials/ksops-generator.prod.yaml b/kargo/credentials/ksops-generator.prod.yaml new file mode 100644 index 0000000..2c7c6b1 --- /dev/null +++ b/kargo/credentials/ksops-generator.prod.yaml @@ -0,0 +1,14 @@ +# ksops generator for PROD cluster +# Replace ksops-generator.yaml on infra/stage/prod branch +apiVersion: viaduct.ai/v1 +kind: ksops +metadata: + name: kargo-git-credentials + annotations: + config.kubernetes.io/function: | + exec: + path: ksops +files: + - git-creds-infra.prod.enc.yaml + - git-creds-ci.prod.enc.yaml + - git-creds-test-env.prod.enc.yaml diff --git a/kargo/credentials/ksops-generator.yaml b/kargo/credentials/ksops-generator.yaml new file mode 100644 index 0000000..9c2337e --- /dev/null +++ b/kargo/credentials/ksops-generator.yaml @@ -0,0 +1,20 @@ +# ksops generator: decrypts SOPS-encrypted K8s Secret manifests +# ArgoCD repo-server must have ksops + sops + age installed +# +# Dev cluster uses: *.dev.enc.yaml +# Prod cluster uses: *.prod.enc.yaml +# +# Which files to decrypt is controlled by the kustomization overlay +# in the cluster-specific branch (infra/stage/dev or infra/stage/prod) +apiVersion: viaduct.ai/v1 +kind: ksops +metadata: + name: kargo-git-credentials + annotations: + config.kubernetes.io/function: | + exec: + path: ksops +files: + - git-creds-infra.dev.enc.yaml + - git-creds-ci.dev.enc.yaml + - git-creds-test-env.dev.enc.yaml diff --git a/kargo/credentials/kustomization.yaml b/kargo/credentials/kustomization.yaml new file mode 100644 index 0000000..e87131a --- /dev/null +++ b/kargo/credentials/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +generators: + - ksops-generator.yaml diff --git a/kargo/infra/kustomization.yaml b/kargo/infra/kustomization.yaml new file mode 100644 index 0000000..fc57428 --- /dev/null +++ b/kargo/infra/kustomization.yaml @@ -0,0 +1,12 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - namespace.yaml + - project.yaml + - warehouse.yaml + - stages/dev.yaml + - stages/test.yaml + - stages/prod.yaml + - verification/rbac.yaml + - verification/dev-health-check.yaml + - verification/prod-health-check.yaml diff --git a/kargo/infra/namespace.yaml b/kargo/infra/namespace.yaml new file mode 100644 index 0000000..8444f9b --- /dev/null +++ b/kargo/infra/namespace.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: infra + labels: + kargo.akuity.io/project: "true" diff --git a/kargo/infra/project.yaml b/kargo/infra/project.yaml new file mode 100644 index 0000000..4552f12 --- /dev/null +++ b/kargo/infra/project.yaml @@ -0,0 +1,18 @@ +apiVersion: kargo.akuity.io/v1alpha1 +kind: Project +metadata: + name: infra +--- +apiVersion: kargo.akuity.io/v1alpha1 +kind: ProjectConfig +metadata: + name: infra + namespace: infra +spec: + promotionPolicies: + - stageSelector: { name: dev } + autoPromotionEnabled: true + - stageSelector: { name: test } + autoPromotionEnabled: true + - stageSelector: { name: prod } + autoPromotionEnabled: true # creates PR, not direct push diff --git a/kargo/infra/stages/dev.yaml b/kargo/infra/stages/dev.yaml new file mode 100644 index 0000000..8207672 --- /dev/null +++ b/kargo/infra/stages/dev.yaml @@ -0,0 +1,69 @@ +apiVersion: kargo.akuity.io/v1alpha1 +kind: Stage +metadata: + name: dev + namespace: infra +spec: + requestedFreight: + - origin: + kind: Warehouse + name: infra-charts + sources: + direct: true + promotionTemplate: + spec: + vars: + - name: gitopsRepo + value: https://github.com/Kargones/deploy-app-kargo-private.git + - name: targetBranch + value: infra/stage/${{ ctx.stage }} + steps: + - uses: git-clone + config: + repoURL: ${{ vars.gitopsRepo }} + checkout: + - branch: main + path: ./src + - branch: ${{ vars.targetBranch }} + create: true + path: ./out + - uses: git-clear + config: + path: ./out + - uses: yaml-update + as: update-cert-manager + config: + path: ./src/infra/cert-manager/config.yaml + updates: + - key: source.targetRevision + value: ${{ chartFrom("https://charts.jetstack.io", "cert-manager").Version }} + - uses: yaml-update + as: update-argo-rollouts + config: + path: ./src/infra/argo-rollouts/config.yaml + updates: + - key: source.targetRevision + value: ${{ chartFrom("https://argoproj.github.io/argo-helm", "argo-rollouts").Version }} + - uses: yaml-update + as: update-gitea + config: + path: ./src/infra/gitea/config.yaml + updates: + - key: source.targetRevision + value: ${{ chartFrom("https://dl.gitea.com/charts", "gitea").Version }} + - uses: copy + config: + inPath: ./src/infra + outPath: ./out/infra + - uses: git-commit + as: commit + config: + path: ./out + message: "promote(infra/${{ ctx.stage }}): freight ${{ ctx.targetFreight.name }}" + - uses: git-push + config: + path: ./out + targetBranch: ${{ vars.targetBranch }} + verification: + analysisTemplates: + - name: dev-health-check diff --git a/kargo/infra/stages/prod.yaml b/kargo/infra/stages/prod.yaml new file mode 100644 index 0000000..db8da8c --- /dev/null +++ b/kargo/infra/stages/prod.yaml @@ -0,0 +1,76 @@ +apiVersion: kargo.akuity.io/v1alpha1 +kind: Stage +metadata: + name: prod + namespace: infra +spec: + requestedFreight: + - origin: + kind: Warehouse + name: infra-charts + sources: + stages: + - test + promotionTemplate: + spec: + vars: + - name: gitopsRepo + value: https://github.com/Kargones/deploy-app-kargo-private.git + - name: sourceBranch + value: infra/stage/test + - name: targetBranch + value: infra/stage/prod + steps: + - uses: git-clone + config: + repoURL: ${{ vars.gitopsRepo }} + checkout: + - branch: ${{ vars.sourceBranch }} + path: ./src + - branch: ${{ vars.targetBranch }} + create: true + path: ./out + - uses: git-clear + config: + path: ./out + - uses: copy + config: + inPath: ./src/infra + outPath: ./out/infra + - uses: git-commit + as: commit + config: + path: ./out + message: "promote(infra/prod): freight ${{ ctx.targetFreight.name }}" + - uses: git-push + as: push + config: + path: ./out + generateTargetBranch: true + - uses: git-open-pr + as: open-pr + config: + repoURL: ${{ vars.gitopsRepo }} + sourceBranch: ${{ outputs.push.branch }} + targetBranch: ${{ vars.targetBranch }} + title: "promote(infra/prod): ${{ ctx.targetFreight.name }}" + description: | + ## Kargo Promotion + **Freight:** ${{ ctx.targetFreight.name }} + **Project:** infra + **Stage:** prod + + ## Verified in + - ✅ dev (pod-health) + - ✅ test (pod-health) + + ## Review + Check the diff below for version changes. + Verify changelogs before merging. + - uses: git-wait-for-pr + config: + repoURL: ${{ vars.gitopsRepo }} + prNumber: ${{ outputs['open-pr'].pr.id }} + verification: + analysisTemplates: + - name: prod-health-check diff --git a/kargo/infra/stages/test.yaml b/kargo/infra/stages/test.yaml new file mode 100644 index 0000000..bc157fc --- /dev/null +++ b/kargo/infra/stages/test.yaml @@ -0,0 +1,51 @@ +apiVersion: kargo.akuity.io/v1alpha1 +kind: Stage +metadata: + name: test + namespace: infra +spec: + requestedFreight: + - origin: + kind: Warehouse + name: infra-charts + sources: + stages: + - dev + promotionTemplate: + spec: + vars: + - name: gitopsRepo + value: https://github.com/Kargones/deploy-app-kargo-private.git + - name: sourceBranch + value: infra/stage/dev + - name: targetBranch + value: infra/stage/${{ ctx.stage }} + steps: + - uses: git-clone + config: + repoURL: ${{ vars.gitopsRepo }} + checkout: + - branch: ${{ vars.sourceBranch }} + path: ./src + - branch: ${{ vars.targetBranch }} + create: true + path: ./out + - uses: git-clear + config: + path: ./out + - uses: copy + config: + inPath: ./src/infra + outPath: ./out/infra + - uses: git-commit + as: commit + config: + path: ./out + message: "promote(infra/${{ ctx.stage }}): freight ${{ ctx.targetFreight.name }}" + - uses: git-push + config: + path: ./out + targetBranch: ${{ vars.targetBranch }} + verification: + analysisTemplates: + - name: dev-health-check diff --git a/kargo/infra/verification/dev-health-check.yaml b/kargo/infra/verification/dev-health-check.yaml new file mode 100644 index 0000000..84fd606 --- /dev/null +++ b/kargo/infra/verification/dev-health-check.yaml @@ -0,0 +1,37 @@ +apiVersion: argoproj.io/v1alpha1 +kind: AnalysisTemplate +metadata: + name: dev-health-check + namespace: infra +spec: + metrics: + - name: pod-health + successCondition: result == "healthy" + provider: + job: + spec: + template: + spec: + serviceAccountName: kargo-verifier + containers: + - name: check + image: alpine/k8s:1.35.1 + command: [sh, -c] + args: + - | + set -e + echo "Checking pod health..." + cm=$(kubectl get pods -n cert-manager --no-headers 2>/dev/null | grep -c Running || echo 0) + echo "cert-manager running pods: $cm" + ar=$(kubectl get pods -n argo-rollouts --no-headers 2>/dev/null | grep -c Running || echo 0) + echo "argo-rollouts running pods: $ar" + gt=$(kubectl get pods -n gitea --no-headers 2>/dev/null | grep -c Running || echo 0) + echo "gitea running pods: $gt" + if [ "$cm" -ge 1 ] && [ "$ar" -ge 1 ] && [ "$gt" -ge 1 ]; then + echo "healthy" + else + echo "unhealthy" + exit 1 + fi + restartPolicy: Never + backoffLimit: 2 diff --git a/kargo/infra/verification/prod-health-check.yaml b/kargo/infra/verification/prod-health-check.yaml new file mode 100644 index 0000000..1f04b7f --- /dev/null +++ b/kargo/infra/verification/prod-health-check.yaml @@ -0,0 +1,37 @@ +apiVersion: argoproj.io/v1alpha1 +kind: AnalysisTemplate +metadata: + name: prod-health-check + namespace: infra +spec: + metrics: + - name: pod-health + successCondition: result == "healthy" + provider: + job: + spec: + template: + spec: + serviceAccountName: kargo-verifier + containers: + - name: check + image: alpine/k8s:1.35.1 + command: [sh, -c] + args: + - | + set -e + echo "Checking pod health..." + cm=$(kubectl get pods -n cert-manager --no-headers 2>/dev/null | grep -c Running || echo 0) + echo "cert-manager running pods: $cm" + ar=$(kubectl get pods -n argo-rollouts --no-headers 2>/dev/null | grep -c Running || echo 0) + echo "argo-rollouts running pods: $ar" + gt=$(kubectl get pods -n gitea --no-headers 2>/dev/null | grep -c Running || echo 0) + echo "gitea running pods: $gt" + if [ "$cm" -ge 1 ] && [ "$ar" -ge 1 ] && [ "$gt" -ge 1 ]; then + echo "healthy" + else + echo "unhealthy" + exit 1 + fi + restartPolicy: Never + backoffLimit: 2 diff --git a/kargo/infra/verification/rbac.yaml b/kargo/infra/verification/rbac.yaml new file mode 100644 index 0000000..70839be --- /dev/null +++ b/kargo/infra/verification/rbac.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kargo-verifier + namespace: infra +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kargo-verifier-infra +rules: + - apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kargo-verifier-infra +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kargo-verifier-infra +subjects: + - kind: ServiceAccount + name: kargo-verifier + namespace: infra diff --git a/kargo/infra/warehouse.yaml b/kargo/infra/warehouse.yaml new file mode 100644 index 0000000..51dad23 --- /dev/null +++ b/kargo/infra/warehouse.yaml @@ -0,0 +1,22 @@ +apiVersion: kargo.akuity.io/v1alpha1 +kind: Warehouse +metadata: + name: infra-charts + namespace: infra +spec: + subscriptions: + - chart: + repoURL: https://charts.jetstack.io + name: cert-manager + semverConstraint: ">=1.17.0" + discoveryLimit: 5 + - chart: + repoURL: https://argoproj.github.io/argo-helm + name: argo-rollouts + semverConstraint: ">=2.39.0" + discoveryLimit: 5 + - chart: + repoURL: https://dl.gitea.com/charts + name: gitea + semverConstraint: ">=10.6.0" + discoveryLimit: 5 diff --git a/kargo/test-env/kustomization.yaml b/kargo/test-env/kustomization.yaml new file mode 100644 index 0000000..b9319de --- /dev/null +++ b/kargo/test-env/kustomization.yaml @@ -0,0 +1,7 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - namespace.yaml + - project.yaml + - warehouse.yaml + - stages/dev.yaml diff --git a/kargo/test-env/namespace.yaml b/kargo/test-env/namespace.yaml new file mode 100644 index 0000000..012965e --- /dev/null +++ b/kargo/test-env/namespace.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: test-env + labels: + kargo.akuity.io/project: "true" diff --git a/kargo/test-env/project.yaml b/kargo/test-env/project.yaml new file mode 100644 index 0000000..9682277 --- /dev/null +++ b/kargo/test-env/project.yaml @@ -0,0 +1,14 @@ +apiVersion: kargo.akuity.io/v1alpha1 +kind: Project +metadata: + name: test-env +--- +apiVersion: kargo.akuity.io/v1alpha1 +kind: ProjectConfig +metadata: + name: test-env + namespace: test-env +spec: + promotionPolicies: + - stageSelector: { name: dev } + autoPromotionEnabled: true diff --git a/kargo/test-env/stages/dev.yaml b/kargo/test-env/stages/dev.yaml new file mode 100644 index 0000000..fd69697 --- /dev/null +++ b/kargo/test-env/stages/dev.yaml @@ -0,0 +1,45 @@ +apiVersion: kargo.akuity.io/v1alpha1 +kind: Stage +metadata: + name: dev + namespace: test-env +spec: + requestedFreight: + - origin: + kind: Warehouse + name: test-env-images + sources: + direct: true + promotionTemplate: + spec: + vars: + - name: gitopsRepo + value: https://github.com/Kargones/deploy-app-kargo-private.git + - name: targetBranch + value: test-env/stage/${{ ctx.stage }} + steps: + - uses: git-clone + config: + repoURL: ${{ vars.gitopsRepo }} + checkout: + - branch: main + path: ./src + - branch: ${{ vars.targetBranch }} + create: true + path: ./out + - uses: git-clear + config: + path: ./out + - uses: copy + config: + inPath: ./src/test-env + outPath: ./out/test-env + - uses: git-commit + as: commit + config: + path: ./out + message: "promote(test-env/${{ ctx.stage }}): freight ${{ ctx.targetFreight.name }}" + - uses: git-push + config: + path: ./out + targetBranch: ${{ vars.targetBranch }} diff --git a/kargo/test-env/warehouse.yaml b/kargo/test-env/warehouse.yaml new file mode 100644 index 0000000..344cc18 --- /dev/null +++ b/kargo/test-env/warehouse.yaml @@ -0,0 +1,8 @@ +apiVersion: kargo.akuity.io/v1alpha1 +kind: Warehouse +metadata: + name: test-env-images + namespace: test-env +spec: + subscriptions: [] + # TODO: Add container image subscriptions for test services diff --git a/test-env/.gitkeep b/test-env/.gitkeep new file mode 100644 index 0000000..e69de29