From 830ee71bda6984ea66795585b06cd9ce92a6cd8a Mon Sep 17 00:00:00 2001 From: Jamie Tanna Date: Sun, 11 Oct 2026 16:56:43 +0100 Subject: [PATCH] rew! refactor(manager/buildkite): match git-URL plugin refs via the YAML walk As a follow-up to the previous commit, which moved plain `name#version` plugin matching from line-based regex onto the new YAML walk, this carries the git-URL matching over too (`ssh://git@host/org/repo#ref`/`https://host/org/repo#ref`, including the Bitbucket-vs-GitHub datasource split and `.git` suffix stripping), so `extractPluginDep` has a single way of recognising a plugin reference instead of two. This is carried over unchanged from the pre-existing line-based regex - behaviour is identical, just matched against the parsed YAML key instead of a raw line. Splitting it into its own commit keeps the previous commit's diff to the plain-name case only. Co-Authored-By: Claude Sonnet 5 --- lib/modules/manager/buildkite/extract.spec.ts | 98 +++++++++++++++++++ lib/modules/manager/buildkite/extract.ts | 22 +++++ 2 files changed, 120 insertions(+) diff --git a/lib/modules/manager/buildkite/extract.spec.ts b/lib/modules/manager/buildkite/extract.spec.ts index 7f3db946cf..000f39850a 100644 --- a/lib/modules/manager/buildkite/extract.spec.ts +++ b/lib/modules/manager/buildkite/extract.spec.ts @@ -141,6 +141,104 @@ describe('modules/manager/buildkite/extract', () => { ]); }); + it('extracts git-based plugins', () => { + const fileContent = codeBlock` + steps: + - ssh://git@github.company.com/some-org/some-plugin#v3.2.7: + username: abc + - https://github.company.com/some-third-org/some-third-plugin#v0.0.1: + build: app + `; + const res = extractPackageFile(fileContent)?.deps; + expect(res).toEqual([ + { + currentValue: 'v3.2.7', + datasource: 'github-tags', + depName: 'some-org/some-plugin', + registryUrls: ['https://github.company.com'], + }, + { + currentValue: 'v0.0.1', + datasource: 'github-tags', + depName: 'some-third-org/some-third-plugin', + registryUrls: ['https://github.company.com'], + }, + ]); + }); + + it('extracts git-based plugin with .git at the end of its name', () => { + const expectedPackageDependency: PackageDependency = { + currentValue: 'v3.2.7', + datasource: 'github-tags', + depName: 'some-org/some-plugin', + registryUrls: ['https://github.company.com'], + }; + const fileContent = codeBlock` + steps: + - ssh://git@github.company.com/some-org/some-plugin.git#v3.2.7: + `; + const res = extractPackageFile(fileContent)?.deps; + expect(res).toHaveLength(1); + expect(res).toEqual([expectedPackageDependency]); + }); + + it('extracts plugins outside plugins sections', () => { + const fileContent = codeBlock` + .docker-options: &some-options + copy-checkout: true + .python3-container: &python3-container + ssh://git@github.some-domain.com/some-org/some-plugin#v3.2.7: + some-config: some-value + <<: *some-options + `; + const res = extractPackageFile(fileContent)?.deps; + const expectedPackageDependency: PackageDependency = { + currentValue: 'v3.2.7', + datasource: 'github-tags', + depName: 'some-org/some-plugin', + registryUrls: ['https://github.some-domain.com'], + }; + expect(res).toEqual([expectedPackageDependency]); + }); + + it('extracts plugin with preceding ?', () => { + const fileContent = codeBlock` + steps: + - ? ssh://git@github.company.com/some-org/some-plugin.git#v3.2.7 + `; + const res = extractPackageFile(fileContent)?.deps; + const expectedPackageDependency: PackageDependency = { + currentValue: 'v3.2.7', + datasource: 'github-tags', + depName: 'some-org/some-plugin', + registryUrls: ['https://github.company.com'], + }; + expect(res).toEqual([expectedPackageDependency]); + }); + + it('extracts plugin tags from bitbucket', () => { + const fileContent = codeBlock` + steps: + - plugins: + - ssh://git@bitbucket.org/some-org/some-plugin.git#v3.2.7: + - docker-compose#v1.3.2: + `; + const res = extractPackageFile(fileContent)?.deps; + const githubDependency: PackageDependency = { + currentValue: 'v1.3.2', + datasource: 'github-tags', + depName: 'docker-compose', + packageName: 'buildkite-plugins/docker-compose-buildkite-plugin', + }; + const bitbucketDependency: PackageDependency = { + currentValue: 'v3.2.7', + datasource: 'bitbucket-tags', + depName: 'some-org/some-plugin', + registryUrls: ['https://bitbucket.org'], + }; + expect(res).toEqual([bitbucketDependency, githubDependency]); + }); + it('extracts plugin tags with quotes', () => { const fileContent = codeBlock` steps: diff --git a/lib/modules/manager/buildkite/extract.ts b/lib/modules/manager/buildkite/extract.ts index 16b3eaadb2..fe836fe790 100644 --- a/lib/modules/manager/buildkite/extract.ts +++ b/lib/modules/manager/buildkite/extract.ts @@ -2,11 +2,16 @@ import { isObject } from '@sindresorhus/is'; import { logger } from '../../../logger/index.ts'; import { regEx } from '../../../util/regex.ts'; import { parseSingleYaml } from '../../../util/yaml.ts'; +import { BitbucketTagsDatasource } from '../../datasource/bitbucket-tags/index.ts'; import { GithubTagsDatasource } from '../../datasource/github-tags/index.ts'; import { isVersion } from '../../versioning/semver/index.ts'; import type { PackageDependency, PackageFileContent } from '../types.ts'; const pluginKeyRegex = regEx(/^(?[^#\s]+)#(?[^:]+)$/); +const gitPluginRegex = regEx( + /(?:ssh:\/\/git@|https:\/\/)(?[^/]+)\/(?.*)/, +); +const gitSuffixRegex = regEx('\\.git$'); function extractPluginDep(key: string): PackageDependency | null { const match = pluginKeyRegex.exec(key); @@ -16,6 +21,23 @@ function extractPluginDep(key: string): PackageDependency | null { const { depName, currentValue } = match.groups; logger.trace(`Found Buildkite plugin ${depName}`); + // Plugins may simply be git repos. If so, we need to parse out the registry. + const gitPluginMatch = gitPluginRegex.exec(depName); + if (gitPluginMatch?.groups) { + const { registry, gitPluginName } = gitPluginMatch.groups; + const gitDepName = gitPluginName.replace(gitSuffixRegex, ''); + const datasource = + registry === 'bitbucket.org' + ? BitbucketTagsDatasource.id + : GithubTagsDatasource.id; + return { + depName: gitDepName, + currentValue, + registryUrls: [`https://${registry}`], + datasource, + }; + } + if (!isVersion(currentValue)) { logger.debug( `Skipping non-pinned Buildkite current version ${currentValue}`,