diff --git a/lib/manager/nuget/__snapshots__/artifacts.spec.ts.snap b/lib/manager/nuget/__snapshots__/artifacts.spec.ts.snap index 95c1fb964c960e37ff675f05e660e2cf644110db..961ebbd4a6bfca86ab97d173ce1c8aab062b5937 100644 --- a/lib/manager/nuget/__snapshots__/artifacts.spec.ts.snap +++ b/lib/manager/nuget/__snapshots__/artifacts.spec.ts.snap @@ -3,7 +3,25 @@ exports[`updateArtifacts aborts if lock file is unchanged 1`] = ` Array [ Object { - "cmd": "dotnet restore project.csproj --force-evaluate", + "cmd": "dotnet new nugetconfig --output ./others/nuget/not-so-random", + "options": Object { + "cwd": "/tmp/github/some/repo", + "encoding": "utf-8", + "env": Object { + "HOME": "/home/user", + "HTTPS_PROXY": "https://example.com", + "HTTP_PROXY": "http://example.com", + "LANG": "en_US.UTF-8", + "LC_ALL": "en_US", + "NO_PROXY": "localhost", + "PATH": "/tmp/path", + }, + "maxBuffer": 10485760, + "timeout": 900000, + }, + }, + Object { + "cmd": "dotnet restore project.csproj --force-evaluate --configfile others/nuget/not-so-random/nuget.config", "options": Object { "cwd": "/tmp/github/some/repo", "encoding": "utf-8", @@ -28,7 +46,7 @@ exports[`updateArtifacts aborts if no lock file found 1`] = `Array []`; exports[`updateArtifacts authenticates at registries 1`] = ` Array [ Object { - "cmd": "dotnet nuget update source myRegistry --username some-username --password some-password --store-password-in-clear-text", + "cmd": "dotnet new nugetconfig --output ./others/nuget/not-so-random", "options": Object { "cwd": "/tmp/github/some/repo", "encoding": "utf-8", @@ -46,7 +64,7 @@ Array [ }, }, Object { - "cmd": "dotnet restore project.csproj --force-evaluate", + "cmd": "dotnet nuget add source https://my-registry.example.org --name myRegistry --configfile others/nuget/not-so-random/nuget.config --username some-username --password some-password --store-password-in-clear-text", "options": Object { "cwd": "/tmp/github/some/repo", "encoding": "utf-8", @@ -64,7 +82,7 @@ Array [ }, }, Object { - "cmd": "dotnet nuget update source myRegistry --username '' --password '' --store-password-in-clear-text", + "cmd": "dotnet restore project.csproj --force-evaluate --configfile others/nuget/not-so-random/nuget.config", "options": Object { "cwd": "/tmp/github/some/repo", "encoding": "utf-8", @@ -102,7 +120,25 @@ exports[`updateArtifacts does not update lock file when non-proj file is changed exports[`updateArtifacts performs lock file maintenance 1`] = ` Array [ Object { - "cmd": "dotnet restore project.csproj --force-evaluate", + "cmd": "dotnet new nugetconfig --output ./others/nuget/not-so-random", + "options": Object { + "cwd": "/tmp/github/some/repo", + "encoding": "utf-8", + "env": Object { + "HOME": "/home/user", + "HTTPS_PROXY": "https://example.com", + "HTTP_PROXY": "http://example.com", + "LANG": "en_US.UTF-8", + "LC_ALL": "en_US", + "NO_PROXY": "localhost", + "PATH": "/tmp/path", + }, + "maxBuffer": 10485760, + "timeout": 900000, + }, + }, + Object { + "cmd": "dotnet restore project.csproj --force-evaluate --configfile others/nuget/not-so-random/nuget.config", "options": Object { "cwd": "/tmp/github/some/repo", "encoding": "utf-8", @@ -137,7 +173,7 @@ Array [ }, }, Object { - "cmd": "docker run --rm --name=renovate_dotnet --label=renovate_child --user=foobar -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache\\":\\"/tmp/renovate/cache\\" -w \\"/tmp/github/some/repo\\" renovate/dotnet bash -l -c \\"dotnet restore project.csproj --force-evaluate\\"", + "cmd": "docker run --rm --name=renovate_dotnet --label=renovate_child --user=foobar -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache\\":\\"/tmp/renovate/cache\\" -w \\"/tmp/github/some/repo\\" renovate/dotnet bash -l -c \\"dotnet new nugetconfig --output ./others/nuget/not-so-random && dotnet restore project.csproj --force-evaluate --configfile others/nuget/not-so-random/nuget.config\\"", "options": Object { "cwd": "/tmp/github/some/repo", "encoding": "utf-8", @@ -160,7 +196,25 @@ Array [ exports[`updateArtifacts supports global mode 1`] = ` Array [ Object { - "cmd": "dotnet restore project.csproj --force-evaluate", + "cmd": "dotnet new nugetconfig --output ./others/nuget/not-so-random", + "options": Object { + "cwd": "/tmp/github/some/repo", + "encoding": "utf-8", + "env": Object { + "HOME": "/home/user", + "HTTPS_PROXY": "https://example.com", + "HTTP_PROXY": "http://example.com", + "LANG": "en_US.UTF-8", + "LC_ALL": "en_US", + "NO_PROXY": "localhost", + "PATH": "/tmp/path", + }, + "maxBuffer": 10485760, + "timeout": 900000, + }, + }, + Object { + "cmd": "dotnet restore project.csproj --force-evaluate --configfile others/nuget/not-so-random/nuget.config", "options": Object { "cwd": "/tmp/github/some/repo", "encoding": "utf-8", @@ -183,7 +237,25 @@ Array [ exports[`updateArtifacts updates lock file 1`] = ` Array [ Object { - "cmd": "dotnet restore project.csproj --force-evaluate", + "cmd": "dotnet new nugetconfig --output ./others/nuget/not-so-random", + "options": Object { + "cwd": "/tmp/github/some/repo", + "encoding": "utf-8", + "env": Object { + "HOME": "/home/user", + "HTTPS_PROXY": "https://example.com", + "HTTP_PROXY": "http://example.com", + "LANG": "en_US.UTF-8", + "LC_ALL": "en_US", + "NO_PROXY": "localhost", + "PATH": "/tmp/path", + }, + "maxBuffer": 10485760, + "timeout": 900000, + }, + }, + Object { + "cmd": "dotnet restore project.csproj --force-evaluate --configfile others/nuget/not-so-random/nuget.config", "options": Object { "cwd": "/tmp/github/some/repo", "encoding": "utf-8", diff --git a/lib/manager/nuget/artifacts.spec.ts b/lib/manager/nuget/artifacts.spec.ts index 20670eda4c3e3c83a27d61f7c9070382620b30cf..f88cb4a7d997d0ffb56b380aeb486bf8c2c9f4c5 100644 --- a/lib/manager/nuget/artifacts.spec.ts +++ b/lib/manager/nuget/artifacts.spec.ts @@ -8,7 +8,10 @@ import * as docker from '../../util/exec/docker'; import * as _env from '../../util/exec/env'; import * as _hostRules from '../../util/host-rules'; import * as nuget from './artifacts'; -import { determineRegistries as _determineRegistries } from './util'; +import { + determineRegistries as _determineRegistries, + getRandomString as _getRandomString, +} from './util'; jest.mock('child_process'); jest.mock('../../util/exec/env'); @@ -19,6 +22,7 @@ jest.mock('./util'); const exec: jest.Mock<typeof _exec> = _exec as any; const env = mocked(_env); const determineRegistries: jest.Mock<typeof _determineRegistries> = _determineRegistries as any; +const getRandomString: jest.Mock<typeof _getRandomString> = _getRandomString as any; const hostRules = mocked(_hostRules); const config = { @@ -33,6 +37,10 @@ describe('updateArtifacts', () => { jest.resetAllMocks(); jest.resetModules(); env.getChildProcessEnv.mockReturnValue(envMock.basic); + fs.ensureCacheDir.mockImplementation((dirName: string) => + Promise.resolve(dirName) + ); + getRandomString.mockReturnValue('not-so-random' as any); await setUtilConfig(config); docker.resetPrefetchedImages(); }); diff --git a/lib/manager/nuget/artifacts.ts b/lib/manager/nuget/artifacts.ts index 05be802d067eb71377b919f7676084f7ef86fc2a..de5d9d80b8241e7542b96f47f4a9ebb23851448e 100644 --- a/lib/manager/nuget/artifacts.ts +++ b/lib/manager/nuget/artifacts.ts @@ -1,9 +1,12 @@ +import { join } from 'path'; import { id } from '../../datasource/nuget'; import { logger } from '../../logger'; import { ExecOptions, exec } from '../../util/exec'; import { + ensureCacheDir, getSiblingFileName, readLocalFile, + remove, writeLocalFile, } from '../../util/fs'; import * as hostRules from '../../util/host-rules'; @@ -12,32 +15,30 @@ import { UpdateArtifactsConfig, UpdateArtifactsResult, } from '../common'; -import { determineRegistries } from './util'; +import { determineRegistries, getRandomString } from './util'; -async function authenticate( +async function addSourceCmds( packageFileName: string, config: UpdateArtifactsConfig, - cmds: string[] -): Promise<void> { + nugetConfigFile: string +): Promise<string[]> { const registries = ( (await determineRegistries(packageFileName, config.localDir)) || [] ).filter((registry) => registry.name != null); + const result = []; for (const registry of registries) { const { username, password } = hostRules.find({ hostType: id, url: registry.url, }); + let addSourceCmd = `dotnet nuget add source ${registry.url} --name ${registry.name} --configfile ${nugetConfigFile}`; if (username && password) { // Add registry credentials from host rules. - cmds.unshift( - `dotnet nuget update source ${registry.name} --username ${username} --password ${password} --store-password-in-clear-text` - ); - // Ensure that credentials are removed as soon as not necessary anymore. - cmds.push( - `dotnet nuget update source ${registry.name} --username '' --password '' --store-password-in-clear-text` - ); + addSourceCmd += ` --username ${username} --password ${password} --store-password-in-clear-text`; } + result.push(addSourceCmd); } + return result; } async function runDotnetRestore( @@ -49,10 +50,19 @@ async function runDotnetRestore( image: 'renovate/dotnet', }, }; - const cmds = [`dotnet restore ${packageFileName} --force-evaluate`]; - await authenticate(packageFileName, config, cmds); + + const nugetConfigDir = await ensureCacheDir( + `./others/nuget/${getRandomString()}` + ); + const nugetConfigFile = join(nugetConfigDir, 'nuget.config'); + const cmds = [ + `dotnet new nugetconfig --output ${nugetConfigDir}`, + ...(await addSourceCmds(packageFileName, config, nugetConfigFile)), + `dotnet restore ${packageFileName} --force-evaluate --configfile ${nugetConfigFile}`, + ]; logger.debug({ cmd: cmds }, 'dotnet command'); await exec(cmds, execOptions); + await remove(nugetConfigDir); } export async function updateArtifacts({ diff --git a/lib/manager/nuget/util.ts b/lib/manager/nuget/util.ts index 566de7e7100bddf2370ec447f2ff68f8767fcdb7..499a44a046d553b6e38ad34ccd3eb46e8a433757 100644 --- a/lib/manager/nuget/util.ts +++ b/lib/manager/nuget/util.ts @@ -1,3 +1,4 @@ +import cryptoRandomString from 'crypto-random-string'; import findUp from 'find-up'; import * as upath from 'upath'; import { XmlDocument } from 'xmldoc'; @@ -19,6 +20,11 @@ export interface Registry { readonly name?: string; } +/* istanbul ignore next */ +export function getRandomString(): string { + return cryptoRandomString({ length: 16 }); +} + export async function determineRegistries( packageFile: string, localDir: string diff --git a/package.json b/package.json index 82286f2b3db3f44b798eb5ed4694c5ac3be5e071..1e6f471120cd09933f7f4182d0ca316924338b03 100644 --- a/package.json +++ b/package.json @@ -126,6 +126,7 @@ "clean-git-ref": "2.0.1", "commander": "6.2.0", "conventional-commits-detector": "1.0.3", + "crypto-random-string": "3.3.0", "deepmerge": "4.2.2", "delay": "4.4.0", "detect-indent": "6.0.0", diff --git a/yarn.lock b/yarn.lock index 1524dad9fa14ec7a1b66ce81000430e46c7110de..ac5136959a0c682c25f1dd8f66646426fbf5102b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3511,6 +3511,13 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" +crypto-random-string@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-3.3.0.tgz#c7a4682b2a87146a1f8b7378ea2606f95775e7e6" + integrity sha512-teWAwfMb1d6brahYyKqcBEb5Yp8PJPvPOdOonXDnvaKOTmKDFNVE8E3Y2XQuzjNV/3XMwHbrX9fHWvrhRKt4Gg== + dependencies: + type-fest "^0.8.1" + crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" @@ -7751,7 +7758,6 @@ npm@^6.13.0: cmd-shim "^3.0.3" columnify "~1.5.4" config-chain "^1.1.12" - debuglog "*" detect-indent "~5.0.0" detect-newline "^2.1.0" dezalgo "~1.0.3" @@ -7766,7 +7772,6 @@ npm@^6.13.0: has-unicode "~2.0.1" hosted-git-info "^2.8.8" iferr "^1.0.2" - imurmurhash "*" infer-owner "^1.0.4" inflight "~1.0.6" inherits "^2.0.4" @@ -7785,14 +7790,8 @@ npm@^6.13.0: libnpx "^10.2.4" lock-verify "^2.1.0" lockfile "^1.0.4" - lodash._baseindexof "*" lodash._baseuniq "~4.6.0" - lodash._bindcallback "*" - lodash._cacheindexof "*" - lodash._createcache "*" - lodash._getnative "*" lodash.clonedeep "~4.5.0" - lodash.restparam "*" lodash.union "~4.6.0" lodash.uniq "~4.5.0" lodash.without "~4.4.0"