diff --git a/lib/modules/datasource/api.ts b/lib/modules/datasource/api.ts index 386241a255e8382ca20335785a8029857edc4142..4bb76b0b3c60b985a643d3ed5f6927a2e98cd636 100644 --- a/lib/modules/datasource/api.ts +++ b/lib/modules/datasource/api.ts @@ -1,6 +1,7 @@ import { AdoptiumJavaDatasource } from './adoptium-java'; import { ArtifactoryDatasource } from './artifactory'; import { AwsMachineImageDataSource } from './aws-machine-image'; +import { AzurePipelinesTasksDatasource } from './azure-pipelines-tasks'; import { BitBucketTagsDatasource } from './bitbucket-tags'; import { CdnJsDatasource } from './cdnjs'; import { ClojureDatasource } from './clojure'; @@ -51,6 +52,7 @@ export default api; api.set(AdoptiumJavaDatasource.id, new AdoptiumJavaDatasource()); api.set(ArtifactoryDatasource.id, new ArtifactoryDatasource()); api.set(AwsMachineImageDataSource.id, new AwsMachineImageDataSource()); +api.set(AzurePipelinesTasksDatasource.id, new AzurePipelinesTasksDatasource()); api.set(BitBucketTagsDatasource.id, new BitBucketTagsDatasource()); api.set(CdnJsDatasource.id, new CdnJsDatasource()); api.set(ClojureDatasource.id, new ClojureDatasource()); diff --git a/lib/modules/datasource/azure-pipelines-tasks/index.spec.ts b/lib/modules/datasource/azure-pipelines-tasks/index.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..add7ea3b407b11d0dcfde4efe8a36c14da0258b0 --- /dev/null +++ b/lib/modules/datasource/azure-pipelines-tasks/index.spec.ts @@ -0,0 +1,31 @@ +import { getPkgReleases } from '..'; +import { AzurePipelinesTasksDatasource } from '.'; + +describe('modules/datasource/azure-pipelines-tasks/index', () => { + it('returns null for unknown task', async () => { + expect( + await getPkgReleases({ + datasource: AzurePipelinesTasksDatasource.id, + depName: 'unknown', + }) + ).toBeNull(); + }); + + it('supports built-in tasks', async () => { + expect( + await getPkgReleases({ + datasource: AzurePipelinesTasksDatasource.id, + depName: 'AutomatedAnalysis', + }) + ).toEqual({ releases: [{ version: '0.171.0' }, { version: '0.198.0' }] }); + }); + + it('is case insensitive', async () => { + expect( + await getPkgReleases({ + datasource: AzurePipelinesTasksDatasource.id, + depName: 'automatedanalysis', + }) + ).toEqual({ releases: [{ version: '0.171.0' }, { version: '0.198.0' }] }); + }); +}); diff --git a/lib/modules/datasource/azure-pipelines-tasks/index.ts b/lib/modules/datasource/azure-pipelines-tasks/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..72a2c699d878299611e24293286e52e414bd7068 --- /dev/null +++ b/lib/modules/datasource/azure-pipelines-tasks/index.ts @@ -0,0 +1,33 @@ +import dataFiles from '../../../data-files.generated'; +import { id as versioning } from '../../versioning/loose'; +import { Datasource } from '../datasource'; +import type { GetReleasesConfig, ReleaseResult } from '../types'; + +export class AzurePipelinesTasksDatasource extends Datasource { + static readonly id = 'azure-pipelines-tasks'; + + private readonly builtInTasks: Record<string, string[]>; + + constructor() { + super(AzurePipelinesTasksDatasource.id); + this.builtInTasks = JSON.parse( + dataFiles.get('data/azure-pipelines-tasks.json')! + ); + } + + override readonly customRegistrySupport = false; + + override readonly defaultVersioning = versioning; + + getReleases({ + packageName, + }: GetReleasesConfig): Promise<ReleaseResult | null> { + const versions = this.builtInTasks[packageName.toLowerCase()]; + if (versions) { + const releases = versions.map((version) => ({ version })); + return Promise.resolve({ releases }); + } + + return Promise.resolve(null); + } +} diff --git a/lib/modules/datasource/azure-pipelines-tasks/readme.md b/lib/modules/datasource/azure-pipelines-tasks/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..109140e561651261defa8dfa9f9a4ced0cc3f4cc --- /dev/null +++ b/lib/modules/datasource/azure-pipelines-tasks/readme.md @@ -0,0 +1,2 @@ +This datasource returns versions of the [built-in Azure Pipelines tasks](https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/?view=azure-devops). +It does not yet support Azure Pipelines tasks from the [Visual Studio Marketplace](https://marketplace.visualstudio.com/search?target=AzureDevOps&category=Azure%20Pipelines) diff --git a/lib/modules/manager/azure-pipelines/extract.spec.ts b/lib/modules/manager/azure-pipelines/extract.spec.ts index 0563cab3b6dfeeaaef62e48beef144e2d56a121c..82ff78295af0195bbcafce433762c17cc413ea07 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 { AzurePipelinesTasksDatasource } from '../../datasource/azure-pipelines-tasks'; import { extractAzurePipelinesTasks, extractContainer, @@ -96,6 +97,7 @@ describe('modules/manager/azure-pipelines/extract', () => { expect(extractAzurePipelinesTasks('Bash@3')).toEqual({ depName: 'Bash', currentValue: '3', + datasource: AzurePipelinesTasksDatasource.id, }); }); @@ -142,7 +144,13 @@ describe('modules/manager/azure-pipelines/extract', () => { azurePipelinesStages, azurePipelinesFilename ); - expect(res?.deps).toEqual([{ depName: 'Bash', currentValue: '3' }]); + expect(res?.deps).toEqual([ + { + depName: 'Bash', + currentValue: '3', + datasource: AzurePipelinesTasksDatasource.id, + }, + ]); }); it('should extract jobs', () => { @@ -150,7 +158,13 @@ describe('modules/manager/azure-pipelines/extract', () => { azurePipelinesJobs, azurePipelinesFilename ); - expect(res?.deps).toEqual([{ depName: 'Bash', currentValue: '3' }]); + expect(res?.deps).toEqual([ + { + depName: 'Bash', + currentValue: '3', + datasource: AzurePipelinesTasksDatasource.id, + }, + ]); }); it('should extract steps', () => { @@ -158,7 +172,13 @@ describe('modules/manager/azure-pipelines/extract', () => { azurePipelinesSteps, azurePipelinesFilename ); - expect(res?.deps).toEqual([{ depName: 'Bash', currentValue: '3' }]); + expect(res?.deps).toEqual([ + { + depName: 'Bash', + currentValue: '3', + datasource: AzurePipelinesTasksDatasource.id, + }, + ]); }); it('should return null when task alias used', () => { diff --git a/lib/modules/manager/azure-pipelines/extract.ts b/lib/modules/manager/azure-pipelines/extract.ts index 5a8045e7e99c289a7085eb11f8c7cbee951beb4d..dbb80ac654aaca06d17b782e37690dbd5512b0aa 100644 --- a/lib/modules/manager/azure-pipelines/extract.ts +++ b/lib/modules/manager/azure-pipelines/extract.ts @@ -1,6 +1,7 @@ import { load } from 'js-yaml'; import { logger } from '../../../logger'; import { regEx } from '../../../util/regex'; +import { AzurePipelinesTasksDatasource } from '../../datasource/azure-pipelines-tasks'; import { GitTagsDatasource } from '../../datasource/git-tags'; import { getDep } from '../dockerfile/extract'; import type { PackageDependency, PackageFile } from '../types'; @@ -59,6 +60,7 @@ export function extractAzurePipelinesTasks( return { depName: match.groups.name, currentValue: match.groups.version, + datasource: AzurePipelinesTasksDatasource.id, }; } return null; diff --git a/lib/modules/manager/azure-pipelines/index.ts b/lib/modules/manager/azure-pipelines/index.ts index bf14289b5456781adcc526588e44419d72dfa32d..5fc99be02aee5b5b6d20613df85f1a928d0ea9c5 100644 --- a/lib/modules/manager/azure-pipelines/index.ts +++ b/lib/modules/manager/azure-pipelines/index.ts @@ -1,3 +1,4 @@ +import { AzurePipelinesTasksDatasource } from '../../datasource/azure-pipelines-tasks'; import { GitTagsDatasource } from '../../datasource/git-tags'; export { extractPackageFile } from './extract'; @@ -5,4 +6,7 @@ export const defaultConfig = { fileMatch: ['azure.*pipelines?.*\\.ya?ml$'], }; -export const supportedDatasources = [GitTagsDatasource.id]; +export const supportedDatasources = [ + AzurePipelinesTasksDatasource.id, + GitTagsDatasource.id, +];