# Azure DevOps<no value>
// <!-- Required for asciidoctor -->
:toc:
// Set toclevels to be at least your hugo [markup.tableOfContents.endLevel] config key
:toclevels: 4

== 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 link:/docs/core/scm/["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 link:/docs/plugins/actions/azuredevops/["Azure DevOps Pull Request" page]. Without such an action, the branch is pushed and nothing else happens.

== Parameters

{{< resourceparameters "scms" "azuredevops" >}}

`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:

[source,text]
----
<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.

include::content/en/docs/plugins/_azuredevopsAuth.adoc[]

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:

[source,text]
----
<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:

[source,text]
----
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 link:https://www.conventionalcommits.org/[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`:

[source,text]
----
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:

[source,yaml]
----
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).

TIP: To run the same manifest against every repository of an organization instead of a single one, use the link:/docs/plugins/scm/azuredevopssearch/[`azuredevopssearch`] scm.

== Example

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`.

[source,yaml]
----
# updatecli.yaml
{{<include "assets/code_example/docs/plugins/scm/azuredevops/updatecli.d/default.yaml">}}
----
