Skip to content

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:

spec:
  writeBackConfig:
    method: "git"

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.repoURL in the Argo CD Application manifest, or if overridden, from the gitConfig.repository field in the ImageUpdater CR, using credentials specified in the writeBackConfig.method field
  • Check-out the target branch on the local copy. The target branch is taken from the writeBackConfig.gitConfig.branch field in the ImageUpdater CR, or if not specified, from the Argo CD Application manifest .spec.source.targetRevision
  • Create or update .argocd-source-<appName>.yaml in the local repository
  • Commit the changed file to the local repository
  • Push the commit to the remote repository, using credentials specified in the ImageUpdater CR

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.targetRevision does 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 Application manifest is used to define the repository and the path where the .argocd-source-<appName>.yaml should be written to. These are defined in .spec.source.repoURL and .spec.source.path fields, respectively. Additionally, .spec.source.targetRevision is used to define the branch to commit and push the changes to. The branch to use can be overridden by configuration in ImageUpdater CR, see below.

  • An ImageUpdater CR, 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 settings
  • secret:<namespace>/<secret> - namespace and secret name.

Example:

spec:
  writeBackConfig:
    method: "git:secret:argocd-image-updater/git-creds"

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:

spec:
  writeBackConfig:
    method: "git"
    gitConfig:
      repository: "git@github.com:example/example.git"

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:

spec:
  writeBackConfig:
    method: "git"
    gitConfig:
      branch: "main"

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:

spec:
  writeBackConfig:
    method: "git"
    gitConfig:
      branch: "base:target"

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:

spec:
  writeBackConfig:
    method: "git"
    gitConfig:
      branch: ":target"

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:

spec:
  writeBackConfig:
    method: "git"
    gitConfig:
      branch: "main:image-updater-{{.SHA256}}"

The following variables are provided for this template:

  • .Images is 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:
  • .Name holds the full name of the image that was updated
  • .Alias holds the alias of the image that was updated
  • .OldTag holds the tag name or SHA digest previous to the update
  • .NewTag holds the tag name or SHA digest that was updated to
  • .SHA256 is 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:

  1. Pushes the image update commit to an automatically generated head branch (image-updater-<namespace>-<appName>-<sha256>).
  2. 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.:

gitConfig:
  branch: "main"

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 -}}
Note: This template assumes 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:

  • .AppName is the name of the application that is being updated
  • .AppChanges is 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:
    • .Image holds the full name of the image that was updated
    • .OldTag holds the tag name or SHA digest previous to the update
    • .NewTag holds the tag name or SHA digest that was updated to
    • .Labels is 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:

data:
  git.commit-sign-off: "true"
  git.commit-signing-key: 3AA5C34371567BD2

Commit Sign Off can be enabled by setting git.commit-sign-off: "true"