Description

The azuredevops scm plugin clones a repository hosted on Azure DevOps (dev.azure.com or a self-hosted Azure DevOps Server) and pushes changes back to it. It is referenced by a resource through its scmid, as described on the "SCM" page.

Its behavior depends on the stage referencing it:

source and condition

The repository is cloned and the resource works on the files from the branch defined by branch. Nothing is pushed.

target

Updatecli creates a working branch based on branch, commits the changes to it, and pushes that branch. The branch value itself is left untouched.

Important
This plugin does not open pull requests. Pushing a working branch and opening a pull request are two distinct steps: the pull request comes from an actions block of kind azuredevops/pullrequest, documented on the "Azure DevOps Pull Request" page. Without such an action, the branch is pushed and nothing else happens.

Parameters

NameTypeDescriptionRequired
branchstring

“branch” defines the git branch to work on.

default: main

remark:

  • when the Azure DevOps scm is used by a source or a condition, files are read from this branch.
  • when the Azure DevOps scm is used by a target, Updatecli pushes changes to a working branch based on this branch, named “updatecli__” by default.
  • set “workingbranch” to false to push changes directly to this branch.

example:

  • branch: main
commitmessageobject

“commitmessage” defines the settings used to generate commit messages.

remark:

  • the settings apply to every target using this scm.
    bodystring

“body” defines the conventional commit body.

default: empty, which means the body is generated by Updatecli.

remark:

  • see https://www.conventionalcommits.org/en/
    deprecatedtitlestring

“title” is ignored.

deprecated:

  • the commit title is always generated from the target name or description.
    footersstring

“footers” defines the conventional commit footers.

default: empty

remark:

  • see https://www.conventionalcommits.org/en/
    hidecreditboolean

“hidecredit” defines whether the Updatecli credit line is left out of the commit message body.

default: false

remark:

  • if you disable the credit line, please consider sponsoring the Updatecli project, https://github.com/updatecli/updatecli
    scopestring

“scope” defines the conventional commit scope.

default: empty

remark:

  • see https://www.conventionalcommits.org/en/
    squashboolean

“squash” defines whether the commits are squashed into a single commit.

default: false

remark:

  • squashing loses the other commit messages, so setting a meaningful “body” is recommended.
  • when “body” is empty, the squashed commit message is generated from the most recent squashed commit. The title is always generated from the target name or description.
    titlestringTitle is the parsed commit message title (not configurable via YAML). The title is automatically generated from the target name or description.
    typestring

“type” defines the conventional commit type, such as “chore”, “fix” or “feat”.

default: chore

remark:

  • see https://www.conventionalcommits.org/en/
depthinteger

“depth” defines the depth used when cloning the git repository.

default: empty, which means a full clone.

remark:

  • a value greater than 0 creates a shallow clone, so Updatecli cannot see the full git history. Pushing changes may then fail, in which case setting “force” to true may be needed.
  • a negative value is rejected.

example:

  • depth: 1
directorystring

“directory” defines the local path where the git repository is cloned.

default: a directory under the Updatecli temporary directory, such as “/tmp/updatecli/azuredevops//” on Linux.

remark:

  • keep the default value unless you have a good reason to change it, as Updatecli may delete the directory after a pipeline run.
emailstring

“email” defines the email address used to author commits.

default: updatecli-bot@updatecli.io

forceboolean

“force” defines whether Updatecli runs git push --force when pushing changes.

default: true

remark:

  • when true, Updatecli also recreates the working branches that diverged from their base branch.
  • when “workingbranch” is false and “force” is not set, the Azure DevOps scm returns an error, to avoid force pushing to “branch” by mistake. Set “force” explicitly to confirm the behavior.
gpgobject“gpg” defines the GPG key and passphrase used to sign commits.
    passphrasestring“passphrase” defines the passphrase that unlocks “signingkey”.
    signingkeystring

“signingkey” defines the armored GPG private key used to sign commits.

default: empty, which means commits are not signed.

remark:

  • the value is the key content, not a key ID.
  • a private key is sensitive, so avoid writing it in the manifest.
organizationstring

“organization” defines the Azure DevOps organization name.

remark:

  • it is required.

example:

  • organization: updatecli
projectstring

“project” defines the Azure DevOps project containing the repository.

example:

  • project: updatecli
repositorystring

“repository” defines the Azure DevOps repository name.

example:

  • repository: website
singlebranchboolean

“singlebranch” defines whether Updatecli clones and fetches only the configured branch, instead of every branch, tag and other reference of the remote.

default: false

remark:

  • enabling it can make operations much faster on repositories with many branches, tags or other references, because Updatecli skips the fetch that mirrors every remote reference.
  • in some edge cases, Updatecli may then miss a working branch that was already pushed, and open a duplicate pull request.
submodulesboolean

“submodules” defines whether Updatecli clones the git submodules of the repository.

default: true

tokenstring

“token” defines the personal access token used to authenticate with Azure DevOps.

remark:

  • when unset, the environment variable “UPDATECLI_AZURE_DEVOPS_TOKEN” is used.
urlstring

“url” defines the Azure DevOps server URL.

default: https://dev.azure.com

remark:

  • “https://” is added when the URL has no scheme.

example:

  • url: https://dev.azure.com
userstring

“user” defines the name used to author commits.

default: updatecli-bot

usernamestring

“username” defines the username used for git authentication.

remark:

  • when unset, the environment variable “UPDATECLI_AZURE_DEVOPS_USERNAME” is used.
workingbranchboolean

“workingbranch” defines whether Updatecli pushes changes to a temporary working branch based on “branch”, instead of pushing to “branch” directly.

default: true

workingbranchprefixstring

“workingbranchprefix” defines the prefix of the working branch name.

default: updatecli

remark:

  • the working branch name joins the prefix, the target branch and the pipeline ID, separated by “workingbranchseparator”.
  • when set to an empty string, the name starts with the separator, for example “main”.
workingbranchseparatorstring

“workingbranchseparator” defines the separator between the parts of the working branch name.

default: _

organization is validated at load time, leaving it out aborts the run with wrong azure devops configuration. project and repository are needed to locate the repository, which is cloned from:

<url>/<organization>/<project>/_git/<repository>
Note
The table is generated from the Updatecli JSON schema, refreshed by a bot after each release. A recently added parameter (currently singleBranch, which restricts clone and fetch to the configured branch) may work in the binary before it appears there.

Authentication

url defaults to https://dev.azure.com. For Azure DevOps Server, give the base URL of your instance, with or without a scheme; https:// is assumed when none is given, and a trailing slash is removed.

Updatecli supports Personal Access Token (PAT) authentication for interacting with Azure DevOps. You can authenticate using environment variables or directly in your manifest.


1. Personal Access Token via Environment Variables

Set the following environment variables to enable PAT authentication:

  • UPDATECLI_AZURE_DEVOPS_TOKEN: Your Azure DevOps Personal Access Token

  • UPDATECLI_AZURE_DEVOPS_USERNAME: Your Azure DevOps username

Example:

export UPDATECLI_AZURE_DEVOPS_TOKEN="your-pat-token"
export UPDATECLI_AZURE_DEVOPS_USERNAME="your-username"
Note

These variables are read per field: exporting only UPDATECLI_AZURE_DEVOPS_TOKEN is enough to supply the token while the username comes from elsewhere.


2. Personal Access Token via Manifest

You can specify your Personal Access Token directly in your Updatecli manifest under the spec.token and spec.username fields:

scms:
  default:
    kind: azuredevops
    spec:
      organization: myorg
      project: myproject
      repository: myrepo
      token: "{{ requiredEnv `UPDATECLI_AZURE_DEVOPS_TOKEN` }}"
      username: "{{ requiredEnv `UPDATECLI_AZURE_DEVOPS_USERNAME` }}"
Warning

For security reasons, it is recommended to use environment variables or secret management tools (like SOPS) instead of hardcoding tokens in your manifest.


Precedence and Fallback

Which of the two wins depends on the plugin:

azuredevops

The manifest wins. UPDATECLI_AZURE_DEVOPS_TOKEN and UPDATECLI_AZURE_DEVOPS_USERNAME only fill in the fields the manifest leaves empty.

azuredevopssearch

The environment wins. When either variable is set, it overrides the matching manifest field.

Nothing validates that a credential was found at all: only organization is checked when the manifest loads. A missing or wrong token surfaces later, when Updatecli calls the API or clones the repository.


Further Reading


Tip: For best security and maintainability, prefer using environment variables for authentication, and avoid hardcoding secrets in your manifests.

When token is set without a username, Updatecli uses updatecli-bot as the git username (Azure DevOps ignores the username of a PAT, so this only needs to be non-empty).

Working branch

For a target, the working branch is derived from three components joined by a separator:

<workingBranchPrefix><workingBranchSeparator><branch><workingBranchSeparator><pipelineID>

With the defaults (updatecli and ), a pipeline based on main produces updatecli_main<pipelineID>, where pipelineID is a hash derived from the manifest - so the same pipeline reuses the same branch instead of piling up new ones. Characters git refuses in a ref are stripped, and the name is truncated to 255 characters. Setting workingBranchPrefix: "" gives <branch>_<pipelineID>.

branch defaults to main, with a warning in the logs when it is left unset.

Disabling the working branch

workingBranch: false makes Updatecli commit and push straight to branch. Since force defaults to true (meaning git push --force), that combination is refused unless force is also set explicitly:

Better safe than sorry.

Updatecli may be pushing unwanted changes to the branch "main".

Set force: false to push without forcing, or force: true to acknowledge the force push. When force is true, Updatecli also recreates working branches that diverged from their base branch.

Tip
updatecli apply --clean-git-branches deletes, at the end of a run, the working branches that ended up identical to their base branch (those left behind by pipelines that had nothing to change).

Commit message

Updatecli generates conventional commits. The commitMessage parameters (type, scope, body, footers, hideCredit, squash) shape the result.

The commit title always comes from the target’s name, or from its description when name is unset. It is capped at 72 characters minus the room taken by type and scope; the overflow moves into the body. With the default type chore:

Author: updatecli-bot <updatecli-bot@updatecli.io>
Date:   Tue May 4 15:41:44 2021 +0200

    chore: Update key "dependencies[0].version" from file "charts/jenkins/r...

    ... equirements.yaml"

    Made with ❤️️  by updatecli

Setting body replaces the generated body entirely, including that overflow. hideCredit: true drops the credit line. squash: true collapses the commits of the working branch into one (set body when you use it, since the individual messages are lost).

Warning

commitMessage.title is deprecated and ignored. Rename the target instead; Updatecli logs a warning when the field is present.

Note
commitMessage applies to every target linked to the same scm.

Commit signing and identity

gpg.signingkey takes an armored private GPG key and gpg.passphrase its passphrase. Both are secrets:

gpg:
  signingkey: '{{ requiredEnv "GPG_SIGNING_KEY" }}'
  passphrase: '{{ requiredEnv "GPG_PASSPHRASE" }}'

user and email name the commit author, defaulting to updatecli-bot and updatecli-bot@updatecli.io.

Clone behavior

Left unset, directory defaults to <tmp>/updatecli/azuredevops/<project>/<repository> on your system temporary directory. Overriding it is rarely useful, as Updatecli may clean that directory up after a run.

submodules

Defaults to true; set it to false to skip submodule checkout.

depth

Number of commits to fetch. Unset means a full clone. A shallow clone leaves an incomplete history, which can break pushes; force: true is often needed alongside.

singleBranch

Defaults to false, meaning every branch, tag, and ref is fetched. true fetches only branch (much faster on repositories with many refs, at the cost of Updatecli sometimes failing to notice an already published working branch and opening a duplicate pull request).

On a repository with a large number of refs, singleBranch is the option that pays off: it skips the fetch that otherwise mirrors every branch, tag, and pull request ref from the remote. It only applies when branch is set. See Large repositories for a full manifest.

Tip
To run the same manifest against every repository of an organization instead of a single one, use the azuredevopssearch scm.

Example

Default

This pipeline updates the Golang version in a single Azure DevOps repository: the change is committed on a working branch, and the azuredevops/pullrequest action turns that branch into a pull request against main.

# updatecli.yaml
name: Update a file and open an Azure DevOps Pull Request

scms:
  default:
    kind: azuredevops
    spec:
      organization: myorg
      project: myproject
      repository: myrepo
      branch: main
      token: '{{ requiredEnv "UPDATECLI_AZURE_DEVOPS_TOKEN" }}'
      username: '{{ requiredEnv "UPDATECLI_AZURE_DEVOPS_USERNAME" }}'
      user: updatecli
      email: updatecli@example.com

sources:
  golang:
    name: Get the latest Golang version
    kind: golang
    spec:
      versionfilter:
        kind: semver
        pattern: "1.24.x"

targets:
  golang-version:
    name: 'deps(golang): Bump Golang version to {{ source "golang" }}'
    kind: yaml
    scmid: default
    spec:
      file: .github/workflows/*.yaml
      key: '$.jobs.build.steps[?(@.uses =~ /^actions\/setup-go/)].with.go-version'
      searchpattern: true

actions:
  default:
    kind: azuredevops/pullrequest
    scmid: default
    spec:
      title: 'deps(golang): Bump Golang version'

Large repositories

# updatecli.yaml
name: Update a file and open an Azure DevOps Pull Request on a large repository

scms:
  default:
    kind: azuredevops
    spec:
      organization: myorg
      project: myproject
      repository: myrepo
      branch: main
      singleBranch: true
      token: '{{ requiredEnv "UPDATECLI_AZURE_DEVOPS_TOKEN" }}'
      username: '{{ requiredEnv "UPDATECLI_AZURE_DEVOPS_USERNAME" }}'
      user: updatecli
      email: updatecli@example.com

sources:
  golang:
    name: Get the latest Golang version
    kind: golang
    spec:
      versionfilter:
        kind: semver
        pattern: "1.24.x"

targets:
  golang-version:
    name: 'deps(golang): Bump Golang version to {{ source "golang" }}'
    kind: yaml
    scmid: default
    spec:
      file: .github/workflows/*.yaml
      key: '$.jobs.build.steps[?(@.uses =~ /^actions\/setup-go/)].with.go-version'
      searchpattern: true

actions:
  default:
    kind: azuredevops/pullrequest
    scmid: default
    spec:
      title: 'deps(golang): Bump Golang version'