Skip to content

Add an Azure Pipelines ecosystem - #15678

Open
JamieMagee wants to merge 5 commits into
mainfrom
jamiemagee/azure-pipelines-ecosystem
Open

Add an Azure Pipelines ecosystem#15678
JamieMagee wants to merge 5 commits into
mainfrom
jamiemagee/azure-pipelines-ecosystem

Conversation

@JamieMagee

@JamieMagee JamieMagee commented Jul 25, 2026

Copy link
Copy Markdown
Member

What are you trying to accomplish?

Updates task: steps in Azure Pipelines YAML, so a pipeline on Maven@3 gets offered Maven@4.

Versions come from microsoft/azure-pipelines-tasks at its latest release tag. The Azure DevOps API for this needs credentials for a specific organization, which Dependabot doesn't have.

Anything you want to highlight for special attention from reviewers?

Precision is the bit worth reviewing. Pipelines pin the major and the agent picks up minors itself. Maven's newest release is 4.276.0, so comparing whole versions would treat Maven@4 as stale and open a no-op PR. Candidates get truncated to the pinned precision first. GoTool@0.3.1 still updates in full.

Directory names aren't authoritative. ANTV1 declares "name": "Ant", so task.json decides the match.

One shared file changed: azure_pipelines joins PACKAGE_MANAGERS_WITH_RELIABLE_DIRECTORIES, otherwise the commits finder tries compare/3...4 against a repo whose tags are sprint numbers.

Marketplace tasks, GUID references and deprecated majors resolve to nothing on purpose.

How will you know you've accomplished your goal?

93 unit examples, plus 364 in common for the shared change. Rubocop and srb tc clean.

Dry run on microsoft/SDCM bumps NuGetToolInstaller@0 to @1 and correctly no-ops the other four, in 13 requests. DigitalRuby/ExchangeSharp bumps DownloadBuildArtifacts@0 and GitHubRelease@0. Cooldown holds a bump at 10,000 days and lets it through at 30.

Against live data: NodeTool@0 (deprecated) and SonarQubePrepare@7 (Marketplace) are left alone, Ant@1 resolves via ANTV1, GoTool@0.3.1 goes to 0.275.0, Docker@1 to 2.

Checklist

  • I have run the complete test suite to ensure all tests and linters pass. (azure_pipelines specs, rubocop, srb tc, and the common specs covering the one shared file. CI covers the rest.)
  • I have thoroughly tested my code changes to ensure they work as expected, including adding additional tests for new functionality.
  • I have written clear and descriptive commit messages.
  • I have provided a detailed description of the changes in the pull request, including the problem it addresses, how it fixes the problem, and any relevant details about the implementation.
  • I have ensured that the code is well-documented and easy to understand.

Copilot AI review requested due to automatic review settings July 25, 2026 06:15
@JamieMagee
JamieMagee requested a review from a team as a code owner July 25, 2026 06:15

This comment was marked as outdated.

Copilot AI review requested due to automatic review settings July 25, 2026 06:24

This comment was marked as outdated.

Copilot AI review requested due to automatic review settings July 25, 2026 06:34

This comment was marked as outdated.

Copilot AI review requested due to automatic review settings July 25, 2026 06:51

This comment was marked as outdated.

Copilot AI review requested due to automatic review settings July 25, 2026 17:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Comments suppressed due to low confidence (2)

azure_pipelines/lib/dependabot/azure_pipelines/package/package_details_fetcher.rb:237

  • The non-404 fallback is still reachable for a malformed 200 response: parse returns nil (or tag_name can be absent), and this expression then selects master. That recreates the unreleased-version risk this status handling is intended to prevent. Treat an invalid successful response as an error; only the explicit 404 branch should return DEFAULT_REF.
          parsed = parse(response.body)
          tag = parsed.is_a?(Hash) ? parsed["tag_name"] : nil

          tag.is_a?(String) && !tag.empty? ? tag : DEFAULT_REF

azure_pipelines/lib/dependabot/azure_pipelines/file_fetcher.rb:137

  • MAX_CANDIDATES is not enforced while scanning one directory. If a directory contains more than 200 YAML files, this loop appends all of them and pipeline_files subsequently downloads every candidate, defeating the request bound described above. Stop this loop when the candidate limit is reached.
        contents.each do |entry|
          next unless entry.type == "file" && entry.name.match?(YAML_PATTERN)

          candidates << cleaned_path(dir, entry.name)
        end
  • Files reviewed: 67/70 changed files
  • Comments generated: 2
  • Review effort level: Medium

Comment on lines +58 to +60
parsed = begin
YAML.safe_load(content, aliases: true, permitted_classes: [Date, Time])
rescue Psych::Exception => e
Comment on lines +257 to +261
sig { params(directory: String).returns(T.nilable(Time)) }
def first_seen_at(directory)
url = "#{TASKS_API_URL}/commits?path=#{TASKS_DIRECTORY}/#{directory}/task.json&per_page=1"

response = get(url)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants