Update methods¶
Overview¶
Argo CD Image Updater supports several methods to propagate new versions of the images to Argo CD. These methods are also referred to as write back methods.
Currently, the following methods are supported:
-
argocd directly modifies the Argo CD Application resource, using Kubernetes API, depending on Argo CD Image Updater's configuration.
-
git will create a Git commit in your Application's Git repository that holds the information about the image to update to.
Depending on the write back method, further configuration may be possible.
The write back method and its configuration can be specified at multiple levels
in the ImageUpdater custom resource:
- Global level: In
spec.writeBackConfig- applies to all applications unless overridden at the application level - Per application level: In
spec.applicationRefs[].writeBackConfig- overrides the global configuration for specific applications
Application-level configuration takes precedence over global configuration.
argocd write-back method¶
The argocd write-back method directly modifies the Argo CD Application resource
in the cluster, updating the application's source parameters (similar to what
argocd app set --parameter ... would do) to instruct Argo CD to re-render the
manifests using those parameters.
This method is pseudo-persistent. If you delete the Application resource
from the cluster and re-create it, changes made by Image Updater will be gone.
The same is true if you manage your Application resources using Git, and
the version stored in Git is synced over the resource in the cluster. This
method is most suitable for Applications also created imperatively, i.e.
using the Web UI or CLI.
This method is the default and requires no further configuration.
git write-back method¶
Compatibility with Argo CD
The Git write-back method requires a feature in Argo CD that has been introduced with Argo CD v2.0. Git write-back will not work with earlier versions of Argo CD.
The git write-back method uses Git to permanently store its parameter
overrides along with the Application's resource manifests. This will enable
persistent storage of the parameters in Git.
By default, Argo CD Image Updater will store the parameter in a file named
.argocd-source-<appName>.yaml in the path used by the Application to source
its manifests from. This will allow Argo CD to pick up parameters in this
file, when rendering manifests for the Application named <appName>. Using
this approach will also minimize the possibility of merge conflicts, as long
as no other party in your CI will modify this file. Helm parameters in this
file are sorted alphabetically by name to ensure deterministic output.
A note on the application's target revision
Due to the nature of how Git write-back works, your application really
should track a branch instead of a revision. If you track HEAD, a tag
or a certain revision with your application, you must specify the
branch in the writeBackConfig.gitConfig.branch field. But in order for
Argo CD to pick up the change after Image Updater has committed & pushed
the change, you really want to set it up so it tracks a branch.
To use the Git write-back method, configure the writeBackConfig in your
ImageUpdater custom resource:
In order to better decide whether this method is suitable for your use-case, this is the workflow how Argo CD Image Updater performs change to Git:
- Fetch the remote repository from location specified by
.spec.source.repoURLin the Argo CD Application manifest, or if overridden, from thegitConfig.repositoryfield in theImageUpdaterCR, using credentials specified in thewriteBackConfig.methodfield - Check-out the target branch on the local copy. The target branch is taken
from the
writeBackConfig.gitConfig.branchfield in theImageUpdaterCR, or if not specified, from the Argo CD Application manifest.spec.source.targetRevision - Create or update
.argocd-source-<appName>.yamlin the local repository - Commit the changed file to the local repository
- Push the commit to the remote repository, using credentials specified in the
ImageUpdaterCR
The important pieces to this workflow are:
-
Credentials configured in Argo CD will be re-used, unless you override with a dedicated set of credentials
-
Write-back is a commit to the tracking branch of the Application.
-
If
.spec.source.targetRevisiondoes not reference a branch, you will have to specify the branch to use manually (see below)
General configuration¶
Configuration for the Git write-back method comes from two sources:
-
The Argo CD
Applicationmanifest is used to define the repository and the path where the.argocd-source-<appName>.yamlshould be written to. These are defined in.spec.source.repoURLand.spec.source.pathfields, respectively. Additionally,.spec.source.targetRevisionis used to define the branch to commit and push the changes to. The branch to use can be overridden by configuration inImageUpdaterCR, see below. -
An
ImageUpdaterCR, see below
Specifying Git credentials¶
By default, Argo CD Image Updater re-uses the credentials you have configured in Argo CD for accessing the repository.
If you don't want to use credentials configured for Argo CD you can use other credentials stored in a Kubernetes secret,
which needs to be accessible by the Argo CD Image Updater's Service Account. The secret should be specified in
the writeBackConfig.method field using git:<credref> format. Where <credref> might
take one of following values:
repocreds(default) - Git repository credentials configured in Argo CD settingssecret:<namespace>/<secret>- namespace and secret name.
Example:
If the repository is accessed using HTTPS, the secret must contain either user credentials or GitHub app credentials.
If the repository is accessed using user credentials, the secret requires two fields
username which holds the Git username, and password which holds the user's
password or a private access token (PAT) with write access to the repository.
You can generate such a secret using kubectl, e.g.:
kubectl -n argocd-image-updater create secret generic git-creds \
--from-literal=username=someuser \
--from-literal=password=somepassword
If the repository is accessed using GitHub app credentials, the secret requires three fields githubAppID which holds the GitHub Application ID, githubAppInstallationID which holds the GitHub Organization Installation ID, and githubAppPrivateKey which holds the GitHub Application private key. The GitHub Application must be installed into the target repository with write access.
You can generate such a secret using kubectl, e.g.:
kubectl -n argocd-image-updater create secret generic git-creds \
--from-literal=githubAppID=applicationid \
--from-literal=githubAppInstallationID=installationid \
--from-literal=githubAppPrivateKey='-----BEGIN RSA PRIVATE KEY-----PRIVATEKEYDATA-----END RSA PRIVATE KEY-----'
The following optional fields are also supported for GitHub App secrets:
| Secret Key | Description | Default |
|---|---|---|
githubAppEnterpriseBaseUrl |
GitHub Enterprise API base URL (e.g. https://github.example.com/api/v3) |
empty (uses github.com) |
tlsClientCertData |
PEM-encoded client certificate for mTLS | empty |
tlsClientCertKey |
PEM-encoded client private key for mTLS | empty |
insecure |
Skip TLS certificate verification ("true" or "false") |
"false" |
proxy |
HTTP(S) proxy URL | empty |
For example, to use a GitHub Enterprise instance:
kubectl -n argocd-image-updater create secret generic git-creds \
--from-literal=githubAppID=12345 \
--from-literal=githubAppInstallationID=67890 \
--from-literal=githubAppPrivateKey='-----BEGIN RSA PRIVATE KEY-----PRIVATEKEYDATA-----END RSA PRIVATE KEY-----' \
--from-literal=githubAppEnterpriseBaseUrl='https://github.example.com/api/v3' \
--from-literal=insecure='true'
Breaking change: insecure default
In previous versions, TLS verification was always skipped (insecure was
hardcoded to true) when using secret-based GitHub App credentials. This
has been fixed to default to false, matching the behavior of repository
credentials configured through Argo CD settings.
If your GitHub Enterprise instance uses a self-signed or internal CA
certificate and you have not set insecure in your secret, you must either:
- Add
insecure: "true"to your secret, or - Install your CA certificate in the container's trust store
If the repository is accessed using SSH, the secret must contain the field
sshPrivateKey, which holds a SSH private key in OpenSSH-compatible PEM
format. To create such a secret from an existing private key, you can use
kubectl, for example:
kubectl -n argocd-image-updater create secret generic git-creds \
--from-file=sshPrivateKey=~/.ssh/id_rsa
Specifying a repository when using a Helm repository in repoURL¶
By default, Argo CD Image Updater will use the value found in the Application
spec at .spec.source.repoURL as Git repository to check out. But when using
a Helm repository as .spec.source.repoURL GIT will simply fail. To manually
specify the repository to push the changes, specify the
writeBackConfig.gitConfig.repository field.
This value will define the Git repository to use, for example the following would use a GitHub's repository:
Specifying a branch to commit to¶
By default, Argo CD Image Updater will use the value found in the Application
spec at .spec.source.targetRevision as Git branch to check out, commit to
and push back the changes it made. In some scenarios, this might not be what
is desired, and you can (and maybe have to) override the branch to use by
specifying the writeBackConfig.gitConfig.branch field.
This value will define the Git branch to use, for example the
following would use GitHub's default main branch:
Specifying a separate base and commit branch¶
By default, Argo CD Image Updater will checkout, commit, and push back to the
same branch specified above. There are many scenarios where this is not
desired or possible, such as when the default branch is protected. You can
add a separate write-branch by modifying the writeBackConfig.gitConfig.branch
field with additional data, which will create a new branch from the base
branch, and push to this new branch instead:
If you want to specify a write-branch but continue to use the target revision from the application specification, just omit the base branch name:
A static branch name may not be desired for this value, so a simple template
can be created (evaluating using the text/template Golang package) within
the configuration. For example, the following would create a branch named
image-updater-foo/bar-1.1 based on main in the event an image with
the name foo/bar was updated to the new tag 1.1.
spec:
writeBackConfig:
method: "git"
gitConfig:
branch: "main:image-updater{{range .Images}}-{{.Name}}-{{.NewTag}}{{end}}"
Alternatively, to assure unique branch names you could use the SHA256 representation of the changes:
The following variables are provided for this template:
.Imagesis a list of changes that were performed by the update. Each entry in this list is a struct providing the following information for each change:.Nameholds the full name of the image that was updated.Aliasholds the alias of the image that was updated.OldTagholds the tag name or SHA digest previous to the update.NewTagholds the tag name or SHA digest that was updated to.SHA256is a unique SHA256 has representing these changes
Please note that if the output of the template exceeds 255 characters (git branch name limit) it will be truncated.
Git Write-Back Target¶
By default, git write-back will create or update .argocd-source-<appName>.yaml.
If you are using Kustomize and want the image updates available for normal use with kustomize,
you may set the writeBackConfig.gitConfig.writeBackTarget to kustomization. This method commits changes to the Kustomization
file back to git as though you ran kustomize edit set image.
spec:
writeBackConfig:
method: "git" # all git options are supported
gitConfig:
writeBackTarget: "kustomization"
You may also specify which kustomization to update with either a path relative to the project source path...
spec:
writeBackConfig:
method: "git"
gitConfig:
writeBackTarget: "kustomization:../../base"
# if the Application spec.source.path = config/overlays/foo, this would update the kustomization in config/base
...or absolute with respect to the repository:
spec:
writeBackConfig:
method: "git"
gitConfig:
# absolute paths start with /
writeBackTarget: "kustomization:/config/overlays/bar"
Note that the Kustomization directory needs to be specified, not a file, like when using Kustomize.
If you are using Helm and want the image updates parameters available in your values files,
you may set the writeBackConfig.gitConfig.writeBackTarget to helmvalues:<full path to your values file>. This method commits changes to the values
file back that is used to render the Helm template.
spec:
writeBackConfig:
method: "git" # all git options are supported
gitConfig:
writeBackTarget: "helmvalues"
You may also specify which helmvalues to update with either a path relative to the project source path...
spec:
writeBackConfig:
method: "git"
gitConfig:
writeBackTarget: "helmvalues:../../values.yaml"
# if the Application spec.source.path = config/overlays/foo, this would update the helmvalues in config/base
...or absolute with respect to the repository:
spec:
writeBackConfig:
method: "git"
gitConfig:
# absolute paths start with /
writeBackTarget: "helmvalues:/helm/config/test-values.yaml"
Note that using the helmvalues option needs the Helm values filename to be specified in the
writeBackConfig.gitConfig.writeBackTarget.
Git Pull Request¶
The Git Pull Request mode extends the git write-back method so that instead
of pushing directly to the tracking branch, Argo CD Image Updater:
- Pushes the image update commit to an automatically generated head branch
(
image-updater-<namespace>-<appName>-<sha256>). - Opens a pull request or merge request from that head branch into the configured base branch.
If a pull request for the same head → base pair already exists, the controller treats the situation as a successful no-op and does not open a duplicate.
When to use Pull Request mode¶
Use this mode when the target branch is protected and direct pushes are forbidden, or when you want every image update to go through a review workflow before it is merged and applied by Argo CD.
Branch configuration¶
Colon branch format is not supported in PR mode
The base:target shorthand used for separate base and commit branches
is not supported when pullRequest is configured. Specify only the
base branch (the branch the PR will be merged into), e.g.:
Configuring a branch value that contains a colon (:) together with
pullRequest is a validation error and will prevent the ImageUpdater CR
from being reconciled.
The head branch (PR source) is derived automatically by the controller using
the template image-updater-<appNamespace>-<appName>-<sha256>, ensuring a
stable, unique branch name per application and set of image changes.
Credentials¶
PR creation requires credentials that carry a bearer token — either a personal access token (PAT) or a GitHub App. SSH keys cannot be used because they do not provide the HTTP token needed to call the SCM API.
Configure credentials via the writeBackConfig.method field using the
git:secret:<namespace>/<secret> format (see
Specifying Git credentials for how to create the
secret). The author identity of the commits and the PR is derived from those
credentials.
PR title and body¶
The pull request title is taken from the first line of the rendered Git commit message template, and the body from everything after the first newline. If no custom commit message template is configured the defaults are:
- Title:
chore: update images for <namespace>/<appName> - Body:
This pull request was created automatically by argocd-image-updater for application <namespace>/<appName>.
Titles longer than 255 characters and bodies longer than 65 536 characters are truncated automatically.
To customise the title and body, configure the commit message template.
GitHub¶
GitHub pull requests are supported for both github.com and GitHub Enterprise Server. For GitHub Enterprise the API base URL is derived automatically from the repository URL.
spec:
writeBackConfig:
method: "git:secret:argocd-image-updater/git-creds"
gitConfig:
repository: "https://github.com/example/example.git"
branch: "main" # base branch; colon format not supported here
pullRequest:
github: {}
Full example with per-application override and Helm values write-back target:
apiVersion: argocd-image-updater.argoproj.io/v1alpha1
kind: ImageUpdater
metadata:
name: my-image-updater
namespace: argocd
spec:
writeBackConfig:
method: "git:secret:argocd/git-creds"
gitConfig:
repository: "https://github.com/example/example.git"
branch: "main"
pullRequest:
github: {}
applicationRefs:
- namePattern: "my-app"
images:
- alias: "nginx"
imageName: "nginx:1.17.10"
writeBackConfig:
method: "git:secret:argocd/git-creds"
gitConfig:
branch: "main"
writeBackTarget: "helmvalues:/helm/config/values.yaml"
GitLab¶
To create a merge request on GitLab (including self-managed instances),
add pullRequest.gitlab to your gitConfig:
writeBackConfig:
method: "git:secret:argocd/gitlab-creds"
gitConfig:
repository: "https://gitlab.com/org/repo.git"
branch: "main"
writeBackTarget: "helmvalues:/helm/config/values.yaml"
pullRequest:
gitlab: {}
Specifying the user and email address for commits¶
Each Git commit is associated with an author's name and email address. If not
configured, commits performed by Argo CD Image Updater will use
argocd-image-updater <noreply@argoproj.io>
as the author. You can override the author using the
--git-commit-user and --git-commit-email command line switches or set
git.user and git.email
in the argocd-image-updater-config ConfigMap.
Changing the Git commit message¶
You can change the default commit message used by Argo CD Image Updater to some
message that best suites your processes and regulations. For this, a simple
template can be created (evaluating using the text/template Golang package)
and made available through setting the key git.commit-message-template in the
argocd-image-updater-config ConfigMap to the template's contents, e.g.
data:
git.commit-message-template: |
build: automatic update of {{ .AppName }}
{{ range .AppChanges -}}
updates image {{ .Image }} tag '{{ .OldTag }}' to '{{ .NewTag }}'
{{ end -}}
If we want a more detailed message, we can add custom labels during the build process, and use them for adding custom details to the commit messages. The example below uses OCI image labels to show the parent commit in GitHub.
- org.opencontainers.image.source label showing the Git repo URL.
- org.opencontainers.image.revision label showing Git commit SHA
data:
git.commit-message-template: |
build: Automatic update of {{ .AppName }}
{{ range .AppChanges -}}
updates image {{ .Image }} tag '{{ .OldTag }}' to '{{ .NewTag }}'
{{- if index .Labels "org.opencontainers.image.revision" }}
{{- $source := index .Labels "org.opencontainers.image.source" }}
{{- $revision := index .Labels "org.opencontainers.image.revision" }}
Upstream Commit: {{ $source }}/commit/{{ $revision }}
{{ end }}
{{ end -}}
org.opencontainers.image.source contains a clean Git repository URL (e.g., https://github.com/org/repo) without trailing slashes or .git suffixes. Most container build tools automatically generate labels in this format. It also assumes that org.opencontainers.image.revision is provided at build time.
To update the Upstream Commit message for different Git providers, following examples can be used.
1. GitLab: Upstream Commit: {{ $source }}/-/commit/{{ $revision }}.
2. BitBucket: Upstream Commit: {{ $source }}/commits/{{ $revision }}
Two top-level variables are provided to the template:
.AppNameis the name of the application that is being updated.AppChangesis a list of changes that were performed by the update. Each entry in this list is a struct providing the following information for each change:.Imageholds the full name of the image that was updated.OldTagholds the tag name or SHA digest previous to the update.NewTagholds the tag name or SHA digest that was updated to.Labelsis a map of the labels contained in the created Docker/OCI image, and in case no labels are being assigned to created image, an empty map is created
In order to test a template before configuring it for use in Image Updater,
you can store the template you want to use in a temporary file, and then use
the argocd-image-updater template /path/to/file command to render the
template using pre-defined data and see its outcome on the terminal.
Enabling commit signature signing using an SSH or GPG key¶
1. SCM branch protection rules require signed commits¶
Commit signing for SCM branch protection rules require the repository be accessed using HTTPS or SSH with a user account. Repositories accessed using a GitHub App can not be verified when using the git command line at this time.
Each Git commit associated with an author's name and email address can be signed via a private SSH key or GPG key.
Commit signing requires a bot account with a GPG or SSH key and the username and email address configured to match the bot account.
Your preferred signing key must be associated with your bot account. See SCM provider documentation for further details: * GitHub * GitLab * Bitbucket
2. Signing commits for future use with ArgoCD Source Verification Policies¶
Commits can also be signed for use with source verification. In this case signing keys do not need to be associated with an SCM user account.
SSH:
The private key must be mounted and accessible on the argocd-image-updater pod.
Set git.commit-signing-key argocd-image-updater-config ConfigMap to the path of your private key:
data:
git.commit-sign-off: "true"
git.commit-signing-key: /app/ssh-keys/id_rsa
git.commit-signing-method: "ssh"
Create a new SSH secret or use your existing SSH secret:
kubectl -n argocd-image-updater create secret generic ssh-git-creds \
--from-file=sshPrivateKey=~/.ssh/id_rsa
GPG:
The GPG private key must be installed and available in the argocd-image-updater pod.
The git.commit-signing-method defaults to openpgp.
Set git.commit-signing-key in the argocd-image-updater-config ConfigMap to the GPG key ID you want to use: