feat: add azure devops support#8586
Conversation
Signed-off-by: Olblak <me@olblak.com>
Signed-off-by: Olblak <me@olblak.com>
Signed-off-by: Olblak <me@olblak.com>
Signed-off-by: Olblak <me@olblak.com>
Signed-off-by: Olblak <me@olblak.com>
Signed-off-by: Olblak <me@olblak.com>
There was a problem hiding this comment.
Pull request overview
Adds first-class Azure DevOps support to Updatecli by introducing an Azure DevOps SCM implementation, an azuredevopssearch SCM for repository/branch discovery, and an Azure DevOps pull request action, then wires them into the pipeline engine, JSON schema generation, scaffolding templates, and e2e configs.
Changes:
- Introduce Azure DevOps SCM (
azuredevops) plus summary helpers/tests. - Add Azure DevOps repo/branch discovery SCM (
azuredevopssearch) with generator + tests. - Add Azure DevOps pull request action/resource implementation (create/exist/clean) with tests, and integrate into engine/pipeline/schema/scaffold/e2e.
Reviewed changes
Copilot reviewed 28 out of 29 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/plugins/scms/azuredevopssearch/main.go | New azuredevopssearch SCM constructor and client wiring |
| pkg/plugins/scms/azuredevopssearch/spec.go | azuredevopssearch spec definition + validation/sanitization |
| pkg/plugins/scms/azuredevopssearch/specGenerator.go | Project/repo/branch discovery and spec generation |
| pkg/plugins/scms/azuredevopssearch/description.go | Summary output for azuredevopssearch |
| pkg/plugins/scms/azuredevopssearch/main_test.go | Tests for defaults/sanitization and invalid regex |
| pkg/plugins/scms/azuredevopssearch/specGenerator_test.go | Tests for discovery behavior and limits |
| pkg/plugins/scms/azuredevops/main.go | Azure DevOps SCM implementation (clone/checkout/commit/push/etc.) |
| pkg/plugins/scms/azuredevops/summary.go | Summary formatting for Azure DevOps SCM |
| pkg/plugins/scms/azuredevops/summary_test.go | Tests for summary formatting (incl. URL credentials stripping) |
| pkg/plugins/resources/azuredevops/client/main.go | Azure DevOps API client (PAT connection + core/git clients) |
| pkg/plugins/resources/azuredevops/client/spec.go | Azure DevOps client spec + URL helpers (GitURL / PullRequestURL) |
| pkg/plugins/resources/azuredevops/pullrequest/main.go | Azure DevOps pull request action constructor + SCM inheritance |
| pkg/plugins/resources/azuredevops/pullrequest/spec.go | Pull request action spec definition |
| pkg/plugins/resources/azuredevops/pullrequest/utils.go | PR/branch helper logic (find PR, ref lookup, iteration checks) |
| pkg/plugins/resources/azuredevops/pullrequest/exist.go | Action “exist” check implementation |
| pkg/plugins/resources/azuredevops/pullrequest/create.go | PR create/update implementation and body generation |
| pkg/plugins/resources/azuredevops/pullrequest/clean.go | Cleanup logic (close empty PRs) |
| pkg/plugins/resources/azuredevops/pullrequest/main_test.go | Tests for action constructor + refName helper |
| pkg/plugins/resources/azuredevops/pullrequest/create_test.go | Tests for PR body generation/merge behavior |
| pkg/plugins/resources/azuredevops/pullrequest/clean_test.go | Tests for PR cleanup helpers (iterations/refs/head-match retry) |
| pkg/core/pipeline/scm/main.go | Register azuredevops SCM and azuredevopssearch kind handling |
| pkg/core/pipeline/scm/config.go | Include Azure DevOps kinds in SCM JSON schema “oneOf” |
| pkg/core/engine/configuration.go | Expand azuredevopssearch into multiple concrete SCM pipelines |
| pkg/core/pipeline/action/main.go | Register azuredevops/pullrequest action handler + JSON schema |
| pkg/core/pipeline/action/main_test.go | Add validation test case for azuredevops action kind normalization |
| pkg/core/scaffold/assets/updatecli.d/_scm.azuredevops.yaml | Add scaffold partial for Azure DevOps SCM + PR action |
| e2e/updatecli.d/success.d/azuredevops/scm.yaml | Add e2e pipeline manifest for Azure DevOps SCM + PR action |
| go.mod | Add Azure DevOps Go SDK dependencies |
| go.sum | Dependency checksum updates |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Olblak <me@olblak.com>
Don't make project and repository required on the client creation Signed-off-by: Olblak <me@olblak.com>
Signed-off-by: Olblak <me@olblak.com>
Signed-off-by: Olblak <me@olblak.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 28 out of 29 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Olblak <me@olblak.com>
Signed-off-by: Olblak <me@olblak.com>
Signed-off-by: Olblak <me@olblak.com>
Signed-off-by: Olblak <me@olblak.com>
Signed-off-by: Olblak <me@olblak.com>
| t.Run("merges existing markdown body for pull request updates", func(t *testing.T) { | ||
| report := &reports.Action{ | ||
| Title: "test", | ||
| Description: "new update description", | ||
| } | ||
| pr := AzureDevOps{} | ||
|
|
||
| got, err := pr.pullRequestBody("existing body", report, true) | ||
| require.NoError(t, err) | ||
|
|
||
| mergedDescription, err := reports.MergeFromMarkdown("existing body", report.ToActionsMarkdownString()) | ||
| require.NoError(t, err) | ||
|
|
||
| expected, err := utils.GeneratePullRequestBodyMarkdown("", mergedDescription) | ||
| require.NoError(t, err) | ||
|
|
||
| assert.Equal(t, expected, got) |
| # {{ if .scm.email }} | ||
| email: '{{ .scm.email }}' | ||
| # {{ end }} | ||
| url: '{{ .scm.url }}' |
| // Clone runs `git clone`. | ||
| func (a *AzureDevOps) Clone() (string, error) { | ||
|
|
||
| // This global is shared across all SCMs/pipelines in the same process, | ||
| // Clone() mutates the global go-git setting transport.UnsupportedCapabilities and then need to be restored. | ||
| // otherwise it can cause surprising behavior (and data races) when multiple pipelines run or | ||
| // when other SCMs clone/fetch after an Azure DevOps clone. | ||
| currentUnsupportedCapabilities := transport.UnsupportedCapabilities | ||
| defer func() { | ||
| transport.UnsupportedCapabilities = currentUnsupportedCapabilities | ||
| }() | ||
|
|
||
| transport.UnsupportedCapabilities = []capability.Capability{ | ||
| capability.ThinPack, |
|
|
||
| const ( | ||
| DefaultRepositoryLimit = 10 | ||
| ErrOrganizationEmpty = "azure DevOps organization is required for azuredevopssearch SCM" |
| type Spec struct { | ||
| // Organization defines the Azure DevOps organization URL to interact with. | ||
| Organization string `yaml:",omitempty"` | ||
| // "url" defines the Azure DevOps organization URL to interact with. | ||
| URL string `yaml:",omitempty"` | ||
| // "project" defines the Azure DevOps project containing the repository. | ||
| Project string `yaml:",omitempty" jsonschema:"required"` | ||
| // "repository" defines the Azure DevOps repository name. | ||
| Repository string `yaml:",omitempty" jsonschema:"required"` | ||
| // "username" defines the username used for git authentication. | ||
| Username string `yaml:",omitempty"` | ||
| // "token" specifies the personal access token used to authenticate with Azure DevOps. | ||
| Token string `yaml:",omitempty"` | ||
| } | ||
|
|
||
| // Validate validates that a spec contains the required Azure DevOps settings. | ||
| func (s Spec) Validate() error { | ||
| missingParameters := []string{} | ||
|
|
||
| if s.Organization == "" { | ||
| missingParameters = append(missingParameters, "organization") | ||
| } | ||
|
|
||
| if len(missingParameters) > 0 { | ||
| logrus.Errorf("missing parameter(s) [%s]", strings.Join(missingParameters, ",")) | ||
| return fmt.Errorf("wrong azure devops configuration") | ||
| } | ||
|
|
||
| return nil | ||
| } |
Signed-off-by: Olblak <me@olblak.com>
Signed-off-by: Olblak <me@olblak.com>
Signed-off-by: Olblak <me@olblak.com>
Signed-off-by: Olblak <me@olblak.com>
Signed-off-by: Olblak <me@olblak.com>
Signed-off-by: Olblak <me@olblak.com>
Fix #7090
This pull request introduces support for Azure DevOps.
azuredevopscan now be used to interact with Azure DevOps repositories.azuredevopssearchis a special scm plugin that allows to interact with all Azure DevOps repositories from an organization matching specific regex rules.azuredevops/pullrequestcan be used to automatically open pull request on a Azure DevOps repository. This action is compatible with the scm of kindazuredevopsandazuredevopssearchWhen a scm is specified then Updatecli clone the repository in a temporary location and run all git operation from there.
Credentials
Credentials can be specified either using the spec parameter
usernameandtoken, or using the environment variableUPDATECLI_AZURE_DEVOPS_USERNAMEandUPDATECLI_AZURE_DEVOPS_TOKEN. The token must be a Personal Access Token (PAT) with the appropriate permissions to access the repositories and create pull requests.If the environment variable is specified, then it overrides the credentials specified in the spec parameters.
Examples
Azure DevOps repository
Azure DevOps Search
Test
To test this pull request, you can run the following commands:
Additional Information
Checklist
Tradeoff
Potential improvement