diff --git a/lib/modules/manager/git-submodules/extract.spec.ts b/lib/modules/manager/git-submodules/extract.spec.ts index 6850f30f1930f47bd3cc04f231f349b0b3e67d1b..c6e53cc5ea7f5c024542eb89622f414a8bcf67c0 100644 --- a/lib/modules/manager/git-submodules/extract.spec.ts +++ b/lib/modules/manager/git-submodules/extract.spec.ts @@ -57,6 +57,29 @@ describe('modules/manager/git-submodules/extract', () => { expect(res?.deps[0].currentValue).toBe('main'); }); + it('default branch is detected with using git environment variables when no branch is specified', async () => { + gitMock.listRemote.mockResolvedValueOnce( + 'ref: refs/heads/main HEAD\n5701164b9f5edba1f6ca114c491a564ffb55a964 HEAD' + ); + hostRules.add({ + hostType: 'github', + matchHost: 'github.com', + token: 'abc123', + }); + const res = await extractPackageFile('', '.gitmodules.2', {}); + expect(res?.deps).toHaveLength(1); + expect(res?.deps[0].currentValue).toBe('main'); + expect(gitMock.env).toHaveBeenCalledWith({ + GIT_CONFIG_COUNT: '3', + GIT_CONFIG_KEY_0: 'url.https://ssh:abc123@github.com/.insteadOf', + GIT_CONFIG_KEY_1: 'url.https://git:abc123@github.com/.insteadOf', + GIT_CONFIG_KEY_2: 'url.https://abc123@github.com/.insteadOf', + GIT_CONFIG_VALUE_0: 'ssh://git@github.com/', + GIT_CONFIG_VALUE_1: 'git@github.com:', + GIT_CONFIG_VALUE_2: 'https://github.com/', + }); + }); + it('default to master if no branch can be detected', async () => { const res = await extractPackageFile('', '.gitmodules.2', {}); expect(res?.deps).toHaveLength(1); diff --git a/lib/modules/manager/git-submodules/extract.ts b/lib/modules/manager/git-submodules/extract.ts index 468a89a747ee1f61db2459cdb14cda0467894d24..b38aef1677d7a0b133d4e1e081ed1c3fdfbd1316 100644 --- a/lib/modules/manager/git-submodules/extract.ts +++ b/lib/modules/manager/git-submodules/extract.ts @@ -4,6 +4,7 @@ import upath from 'upath'; import { GlobalConfig } from '../../../config/global'; import { logger } from '../../../logger'; import { detectPlatform } from '../../../util/common'; +import { getGitEnvironmentVariables } from '../../../util/git/auth'; import { simpleGitConfig } from '../../../util/git/config'; import { getHttpUrl, getRemoteUrlWithToken } from '../../../util/git/url'; import { regEx } from '../../../util/regex'; @@ -37,11 +38,16 @@ async function getUrl( const headRefRe = regEx(/ref: refs\/heads\/(?<branch>\w+)\s/); async function getDefaultBranch(subModuleUrl: string): Promise<string> { - const val = await Git(simpleGitConfig()).listRemote([ - '--symref', - subModuleUrl, - 'HEAD', - ]); + const gitSubmoduleAuthEnvironmentVariables = getGitEnvironmentVariables(); + const gitEnv = { + // pass all existing env variables + ...process.env, + // add all known git Variables + ...gitSubmoduleAuthEnvironmentVariables, + }; + const val = await Git(simpleGitConfig()) + .env(gitEnv) + .listRemote(['--symref', subModuleUrl, 'HEAD']); return headRefRe.exec(val)?.groups?.branch ?? 'master'; } diff --git a/lib/modules/manager/git-submodules/readme.md b/lib/modules/manager/git-submodules/readme.md index 680c780f157855f00652859ca3ab01cb1dfe247b..a6194f456ca6dd87a058e44118b0c01d01449700 100644 --- a/lib/modules/manager/git-submodules/readme.md +++ b/lib/modules/manager/git-submodules/readme.md @@ -1,7 +1,4 @@ -Keeps publicly accessible Git submodules updated within a repository. - -Renovate does not support updating Git submodules that are hosted on a private repository. -Subscribe to [issue #10149 on GitHub](https://github.com/renovatebot/renovate/issues/10149) to keep track of our progress towards supporting private Git submodules. +Keeps Git submodules updated within a repository. You can customize the per-submodule checks of the git-submodules manager like this: @@ -13,3 +10,19 @@ You can customize the per-submodule checks of the git-submodules manager like th } } ``` + +### Private Modules Authentication + +Before running the `git` commands to update the submodules, Renovate exports `git` [`insteadOf`](https://git-scm.com/docs/git-config#Documentation/git-config.txt-urlltbasegtinsteadOf) directives in environment variables. + +The following logic is executed prior to "submodules" updating: + +The token from the `hostRules` entry matching `hostType=github` and `matchHost=api.github.com` is added as the default authentication for `github.com`. +For those running against `github.com`, this token will be the default platform token. + +Next, all `hostRules` with both a token and `matchHost` will be fetched, except for any github.com one from above. + +Rules from this list are converted to environment variable directives if they match _any_ of the following characteristics: + +- No `hostType` is defined, or +- `hostType` is a platform (`github`, `gitlab`, `azure`, etc.) diff --git a/lib/modules/manager/git-submodules/update.spec.ts b/lib/modules/manager/git-submodules/update.spec.ts index 6b5111ed5cea27cb4a6e099e1c989dbad7430fd2..2b77fd380385f4ae985bf744fbfcd45644f1d007 100644 --- a/lib/modules/manager/git-submodules/update.spec.ts +++ b/lib/modules/manager/git-submodules/update.spec.ts @@ -62,5 +62,30 @@ describe('modules/manager/git-submodules/update', () => { }); expect(update).toBe(''); }); + + it('returns content on update and uses git environment variables', async () => { + gitMock.submoduleUpdate.mockResolvedValue(''); + gitMock.checkout.mockResolvedValue(''); + hostRules.add({ + hostType: 'github', + matchHost: 'github.com', + token: 'abc123', + }); + + const update = await updateDependency({ + fileContent: '', + upgrade, + }); + expect(update).toBe(''); + expect(gitMock.env).toHaveBeenCalledWith({ + GIT_CONFIG_COUNT: '3', + GIT_CONFIG_KEY_0: 'url.https://ssh:abc123@github.com/.insteadOf', + GIT_CONFIG_KEY_1: 'url.https://git:abc123@github.com/.insteadOf', + GIT_CONFIG_KEY_2: 'url.https://abc123@github.com/.insteadOf', + GIT_CONFIG_VALUE_0: 'ssh://git@github.com/', + GIT_CONFIG_VALUE_1: 'git@github.com:', + GIT_CONFIG_VALUE_2: 'https://github.com/', + }); + }); }); }); diff --git a/lib/modules/manager/git-submodules/update.ts b/lib/modules/manager/git-submodules/update.ts index 54df033376cba57c611fa2914e4284977d74126a..75eae26982f35436393490af2cdb8dd7e2c91591 100644 --- a/lib/modules/manager/git-submodules/update.ts +++ b/lib/modules/manager/git-submodules/update.ts @@ -2,6 +2,7 @@ import Git from 'simple-git'; import upath from 'upath'; import { GlobalConfig } from '../../../config/global'; import { logger } from '../../../logger'; +import { getGitEnvironmentVariables } from '../../../util/git/auth'; import type { UpdateDependencyConfig } from '../types'; export default async function updateDependency({ @@ -9,7 +10,14 @@ export default async function updateDependency({ upgrade, }: UpdateDependencyConfig): Promise<string | null> { const localDir = GlobalConfig.get('localDir'); - const git = Git(localDir); + const gitSubmoduleAuthEnvironmentVariables = getGitEnvironmentVariables(); + const gitEnv = { + // pass all existing env variables + ...process.env, + // add all known git Variables + ...gitSubmoduleAuthEnvironmentVariables, + }; + const git = Git(localDir).env(gitEnv); const submoduleGit = Git(upath.join(localDir, upgrade.depName)); try {