diff --git a/lib/manager/npm/extract/__snapshots__/index.spec.ts.snap b/lib/manager/npm/extract/__snapshots__/index.spec.ts.snap index 5037b09dd13ae6..27ab170d49176b 100644 --- a/lib/manager/npm/extract/__snapshots__/index.spec.ts.snap +++ b/lib/manager/npm/extract/__snapshots__/index.spec.ts.snap @@ -296,6 +296,19 @@ Object { "prettyDepType": "dependency", "sourceUrl": "https://github.com/owner/n", }, + Object { + "currentRawValue": "git@github.com:owner/o.git#v2.0.0", + "currentValue": "v2.0.0", + "datasource": "github-tags", + "depName": "o", + "depType": "dependencies", + "gitRef": true, + "githubRepo": "owner/o", + "lookupName": "owner/o", + "pinDigests": false, + "prettyDepType": "dependency", + "sourceUrl": "https://github.com/owner/o", + }, ], "lernaClient": undefined, "lernaPackages": undefined, diff --git a/lib/manager/npm/extract/index.spec.ts b/lib/manager/npm/extract/index.spec.ts index f67f4420b6d272..e513d19e92813b 100644 --- a/lib/manager/npm/extract/index.spec.ts +++ b/lib/manager/npm/extract/index.spec.ts @@ -332,6 +332,7 @@ describe('manager/npm/extract/index', () => { l: 'github:owner/l.git#abcdef0', m: 'https://github.com/owner/m.git#v1.0.0', n: 'git+https://github.com/owner/n#v2.0.0', + o: 'git@github.com:owner/o.git#v2.0.0', }, }; const pJsonStr = JSON.stringify(pJson); diff --git a/lib/manager/npm/extract/index.ts b/lib/manager/npm/extract/index.ts index 7b2156cfce42f3..4cf396790500b0 100644 --- a/lib/manager/npm/extract/index.ts +++ b/lib/manager/npm/extract/index.ts @@ -30,6 +30,9 @@ function parseDepName(depType: string, key: string): string { return depName; } +const RE_REPOSITORY_GITHUB_SSH_FORMAT = + /(?:git@)github.com:([^/]+)\/([^/.]+)(?:\.git)?/; + export async function extractPackageFile( content: string, fileName: string, @@ -258,17 +261,28 @@ export async function extractPackageFile( return dep; } const [depNamePart, depRefPart] = hashSplit; - const githubOwnerRepo = depNamePart - .replace(/^github:/, '') - .replace(/^git\+/, '') - .replace(/^https:\/\/github\.com\//, '') - .replace(/\.git$/, ''); - const githubRepoSplit = githubOwnerRepo.split('/'); - if (githubRepoSplit.length !== 2) { - dep.skipReason = SkipReason.UnknownVersion; - return dep; + + let githubOwnerRepo: string; + let githubOwner: string; + let githubRepo: string; + const matchUrlSshFormat = RE_REPOSITORY_GITHUB_SSH_FORMAT.exec(depNamePart); + if (matchUrlSshFormat === null) { + githubOwnerRepo = depNamePart + .replace(/^github:/, '') + .replace(/^git\+/, '') + .replace(/^https:\/\/github\.com\//, '') + .replace(/\.git$/, ''); + const githubRepoSplit = githubOwnerRepo.split('/'); + if (githubRepoSplit.length !== 2) { + dep.skipReason = SkipReason.UnknownVersion; + return dep; + } + [githubOwner, githubRepo] = githubRepoSplit; + } else { + githubOwner = matchUrlSshFormat[1]; + githubRepo = matchUrlSshFormat[2]; + githubOwnerRepo = `${githubOwner}/${githubRepo}`; } - const [githubOwner, githubRepo] = githubRepoSplit; const githubValidRegex = /^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$/; if ( !githubValidRegex.test(githubOwner) ||