In my GitOps workflow, I faced a unique challenge: the application repository and the GitOps repository were separate. I needed a way to make ArgoCD track pull requests (PRs) in the application repository while still handling deployments through the GitOps repository.
To solve this, I created a Kubernetes Secret containing a personal access token (PAT). This token allowed ArgoCD to access the application repository and track PRs easily.
Here’s the YAML configuration for the Secret:
apiVersion: v1
kind: Secret
metadata:
name: argocd-project-pat-secret
namespace: argocd
type: Opaque
data:
token: {{ .Values.argocd.patToken | b64enc }}
This Secret securely stores the token, ensuring ArgoCD has the necessary permissions to monitor the application repository.
In my GitOps setup, I created two types of environments using ArgoCD’s ApplicationSets:
-
Ephemeral Environments: These environments are automatically generated from pull requests. Each PR creates a unique namespace, providing an isolated environment for testing without affecting others.
-
Persistent Environments: For stable environments like QA and production, I use a list generator to manage them. These environments are deployed using a custom Helm chart, ensuring they are consistent and reliable.
Both types of environments are deployed using our custom Helm charts, We have the following Helm release files for the environments:
ephemeral-helm-release.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: dog-eph-helm-releases
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ["missingkey=error"]
generators:
- pullRequest:
requeueAfterSeconds: 30
github:
owner: dog
repo: dog.dog
tokenRef:
secretName: argocd-pat-secret
key: token
template:
metadata:
name: 'dog-pr{{ .number}}-helm-release'
spec:
project: default
source:
path: backend/chart
repoURL: https://github.com/dog/dog.git
helm:
releaseName: dog-pr{{ .number}}
values: |
postgres:
enabled: true
nodeSelector:
node-pool: "system"
destination:
server: "https://<your-cluster-api-server>:6443"
namespace: dog-pr{{ .number}}
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- ServerSideApply=true
persistent-helm-release.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: dog-persist-helm-release
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ["missingkey=error"]
generators:
- list:
elements:
- env: qa
- env: prod
template:
metadata:
name: 'dog-{{ .env}}-helm-release'
spec:
project: default
source:
path: backend/chart
repoURL: https://github.com/dog/dog.git
helm:
releaseName: dog-{{ .env}}
values: |
postgres:
enabled: false
secretName: dog-db-{{ .env}}-secret
configMapName: dog-postgres-{{ .env}}-cm
jwt:
secretName: dog-jwt-{{ .env}}-secret
nodeSelector:
node-pool: "system"
destination:
server: "https://<your-cluster-api-server>:6443"
namespace: dog-{{ .env}}
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- ServerSideApply=trueWith this setup, ArgoCD automatically detects and deploys changes whenever a PR is opened or updated in the application repository. These changes are deployed to a preview environment, allowing me to test and validate updates in real time. This process removed the need for manual testing steps for PRs and made feedback much faster.
By automating PR-based deployments, I was able to make the entire process easier and more reliable. This approach saved time and improved how deployments were handled.
If you’re working with separate repositories in your GitOps setup, this method can help you manage PR-driven deployments efficiently.