From 2ed30c076431a293a617b8682c5ef0efa5f97662 Mon Sep 17 00:00:00 2001 From: Tom Fay <tom@teamfay.co.uk> Date: Wed, 15 Feb 2023 06:14:47 +0000 Subject: [PATCH] fix(manager/azure-pipelines): Enable azure repository extraction (#20380) --- .../manager/azure-pipelines/extract.spec.ts | 52 +++++++++++++++++++ .../manager/azure-pipelines/extract.ts | 36 ++++++++++++- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/lib/modules/manager/azure-pipelines/extract.spec.ts b/lib/modules/manager/azure-pipelines/extract.spec.ts index 82ff78295a..84b198a997 100644 --- a/lib/modules/manager/azure-pipelines/extract.spec.ts +++ b/lib/modules/manager/azure-pipelines/extract.spec.ts @@ -1,4 +1,5 @@ import { Fixtures } from '../../../../test/fixtures'; +import { GlobalConfig } from '../../../config/global'; import { AzurePipelinesTasksDatasource } from '../../datasource/azure-pipelines-tasks'; import { extractAzurePipelinesTasks, @@ -19,6 +20,10 @@ const azurePipelinesJobs = Fixtures.get('azure-pipelines-jobs.yaml'); const azurePipelinesSteps = Fixtures.get('azure-pipelines-steps.yaml'); describe('modules/manager/azure-pipelines/extract', () => { + afterEach(() => { + GlobalConfig.reset(); + }); + it('should parse a valid azure-pipelines file', () => { const file = parseAzurePipelines(azurePipelines, azurePipelinesFilename); expect(file).not.toBeNull(); @@ -72,6 +77,53 @@ describe('modules/manager/azure-pipelines/extract', () => { }) ).toBeNull(); }); + + it('should extract Azure repository information if project in name', () => { + GlobalConfig.set({ + platform: 'azure', + endpoint: 'https://dev.azure.com/renovate-org', + }); + + expect( + extractRepository({ + type: 'git', + name: 'project/repo', + ref: 'refs/tags/v1.0.0', + }) + ).toMatchObject({ + depName: 'project/repo', + packageName: 'https://dev.azure.com/renovate-org/project/_git/repo', + }); + }); + + it('should return null if repository type is git and project not in name', () => { + GlobalConfig.set({ + platform: 'azure', + endpoint: 'https://dev.azure.com/renovate-org', + }); + + expect( + extractRepository({ + type: 'git', + name: 'repo', + ref: 'refs/tags/v1.0.0', + }) + ).toBeNull(); + }); + + it('should extract return null for git repo type if platform not Azure', () => { + GlobalConfig.set({ + platform: 'github', + }); + + expect( + extractRepository({ + type: 'git', + name: 'project/repo', + ref: 'refs/tags/v1.0.0', + }) + ).toBeNull(); + }); }); describe('extractContainer()', () => { diff --git a/lib/modules/manager/azure-pipelines/extract.ts b/lib/modules/manager/azure-pipelines/extract.ts index 50cfc49fc4..512ca41124 100644 --- a/lib/modules/manager/azure-pipelines/extract.ts +++ b/lib/modules/manager/azure-pipelines/extract.ts @@ -1,7 +1,9 @@ import { load } from 'js-yaml'; +import { GlobalConfig } from '../../../config/global'; import { logger } from '../../../logger'; import { coerceArray } from '../../../util/array'; import { regEx } from '../../../util/regex'; +import { joinUrlParts } from '../../../util/url'; import { AzurePipelinesTasksDatasource } from '../../datasource/azure-pipelines-tasks'; import { GitTagsDatasource } from '../../datasource/git-tags'; import { getDep } from '../dockerfile/extract'; @@ -13,7 +15,37 @@ const AzurePipelinesTaskRegex = regEx(/^(?<name>[^@]+)@(?<version>.*)$/); export function extractRepository( repository: Repository ): PackageDependency | null { - if (repository.type !== 'github') { + let repositoryUrl = null; + + if (repository.type === 'github') { + repositoryUrl = `https://github.com/${repository.name}.git`; + } else if (repository.type === 'git') { + // "git" type indicates an AzureDevOps repository. + // The repository URL is only deducible if we are running on AzureDevOps (so can use the endpoint) + // and the name is of the form `Project/Repository`. + // The name could just be the repository name, in which case AzureDevOps defaults to the + // same project, which is not currently accessible here. It could be deduced later by exposing + // the repository URL to managers. + // https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema/resources-repositories-repository?view=azure-pipelines#types + const { platform, endpoint } = GlobalConfig.get(); + if (platform === 'azure' && endpoint) { + if (repository.name.includes('/')) { + const [projectName, repoName] = repository.name.split('/'); + repositoryUrl = joinUrlParts( + endpoint, + encodeURIComponent(projectName), + '_git', + encodeURIComponent(repoName) + ); + } else { + logger.debug( + 'Renovate cannot update repositories that do not include the project name' + ); + } + } + } + + if (repositoryUrl === null) { return null; } @@ -27,7 +59,7 @@ export function extractRepository( datasource: GitTagsDatasource.id, depName: repository.name, depType: 'gitTags', - packageName: `https://github.com/${repository.name}.git`, + packageName: repositoryUrl, replaceString: repository.ref, }; } -- GitLab