mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-09 13:36:26 +00:00
Merge b1b1635886
into 141467b9b0
This commit is contained in:
commit
27add0b743
3 changed files with 142 additions and 8 deletions
|
@ -16,6 +16,10 @@ url = "last.url"
|
|||
[[tool.poetry.source]]
|
||||
name = "five"
|
||||
|
||||
[[tool.poetry.source]]
|
||||
name = "invalid-url"
|
||||
url = "invalid-url"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry_core>=1.0", "wheel"]
|
||||
build-backend = "poetry.masonry.api"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { codeBlock } from 'common-tags';
|
||||
import { GoogleAuth as _googleAuth } from 'google-auth-library';
|
||||
import { mockDeep } from 'jest-mock-extended';
|
||||
import { join } from 'upath';
|
||||
import { envMock, mockExecAll } from '../../../../test/exec-util';
|
||||
|
@ -15,16 +16,26 @@ import { updateArtifacts } from '.';
|
|||
|
||||
const pyproject1toml = Fixtures.get('pyproject.1.toml');
|
||||
const pyproject10toml = Fixtures.get('pyproject.10.toml');
|
||||
const pyproject13toml = `[[tool.poetry.source]]
|
||||
name = "some-gar-repo"
|
||||
url = "https://someregion-python.pkg.dev/some-project/some-repo/simple/"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry_core>=1.0", "wheel"]
|
||||
build-backend = "poetry.masonry.api"
|
||||
`;
|
||||
|
||||
jest.mock('../../../util/exec/env');
|
||||
jest.mock('../../../util/fs');
|
||||
jest.mock('../../datasource', () => mockDeep());
|
||||
jest.mock('../../../util/host-rules', () => mockDeep());
|
||||
jest.mock('google-auth-library');
|
||||
|
||||
process.env.CONTAINERBASE = 'true';
|
||||
|
||||
const datasource = mocked(_datasource);
|
||||
const hostRules = mocked(_hostRules);
|
||||
const googleAuth = mocked(_googleAuth);
|
||||
|
||||
const adminConfig: RepoGlobalConfig = {
|
||||
localDir: join('/tmp/github/some/repo'),
|
||||
|
@ -198,7 +209,99 @@ describe('modules/manager/poetry/artifacts', () => {
|
|||
},
|
||||
},
|
||||
]);
|
||||
expect(hostRules.find.mock.calls).toHaveLength(5);
|
||||
expect(hostRules.find.mock.calls).toHaveLength(7);
|
||||
expect(execSnapshots).toMatchObject([
|
||||
{
|
||||
cmd: 'poetry update --lock --no-interaction dep1',
|
||||
options: {
|
||||
env: {
|
||||
POETRY_HTTP_BASIC_ONE_PASSWORD: 'passwordOne',
|
||||
POETRY_HTTP_BASIC_ONE_USERNAME: 'usernameOne',
|
||||
POETRY_HTTP_BASIC_TWO_USERNAME: 'usernameTwo',
|
||||
POETRY_HTTP_BASIC_FOUR_OH_FOUR_PASSWORD: 'passwordFour',
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('passes Google Artifact Registry credentials environment vars', async () => {
|
||||
// poetry.lock
|
||||
fs.getSiblingFileName.mockReturnValueOnce('poetry.lock');
|
||||
fs.readLocalFile.mockResolvedValueOnce(null);
|
||||
// pyproject.lock
|
||||
fs.getSiblingFileName.mockReturnValueOnce('pyproject.lock');
|
||||
fs.readLocalFile.mockResolvedValueOnce('[metadata]\n');
|
||||
const execSnapshots = mockExecAll();
|
||||
fs.readLocalFile.mockResolvedValueOnce('New poetry.lock');
|
||||
googleAuth.mockImplementationOnce(
|
||||
jest.fn().mockImplementationOnce(() => ({
|
||||
getAccessToken: jest.fn().mockResolvedValue('some-token'),
|
||||
})),
|
||||
);
|
||||
const updatedDeps = [{ depName: 'dep1' }];
|
||||
expect(
|
||||
await updateArtifacts({
|
||||
packageFileName: 'pyproject.toml',
|
||||
updatedDeps,
|
||||
newPackageFileContent: pyproject13toml,
|
||||
config,
|
||||
}),
|
||||
).toEqual([
|
||||
{
|
||||
file: {
|
||||
type: 'addition',
|
||||
path: 'pyproject.lock',
|
||||
contents: 'New poetry.lock',
|
||||
},
|
||||
},
|
||||
]);
|
||||
expect(hostRules.find.mock.calls).toHaveLength(3);
|
||||
expect(execSnapshots).toMatchObject([
|
||||
{
|
||||
cmd: 'poetry update --lock --no-interaction dep1',
|
||||
options: {
|
||||
env: {
|
||||
POETRY_HTTP_BASIC_SOME_GAR_REPO_USERNAME: 'oauth2accesstoken',
|
||||
POETRY_HTTP_BASIC_SOME_GAR_REPO_PASSWORD: 'some-token',
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('continues if Google auth is not configured', async () => {
|
||||
// poetry.lock
|
||||
fs.getSiblingFileName.mockReturnValueOnce('poetry.lock');
|
||||
fs.readLocalFile.mockResolvedValueOnce(null);
|
||||
// pyproject.lock
|
||||
fs.getSiblingFileName.mockReturnValueOnce('pyproject.lock');
|
||||
fs.readLocalFile.mockResolvedValueOnce('[metadata]\n');
|
||||
const execSnapshots = mockExecAll();
|
||||
fs.readLocalFile.mockResolvedValueOnce('New poetry.lock');
|
||||
googleAuth.mockImplementation(
|
||||
jest.fn().mockImplementation(() => ({
|
||||
getAccessToken: jest.fn().mockResolvedValue(undefined),
|
||||
})),
|
||||
);
|
||||
const updatedDeps = [{ depName: 'dep1' }];
|
||||
expect(
|
||||
await updateArtifacts({
|
||||
packageFileName: 'pyproject.toml',
|
||||
updatedDeps,
|
||||
newPackageFileContent: pyproject13toml,
|
||||
config,
|
||||
}),
|
||||
).toEqual([
|
||||
{
|
||||
file: {
|
||||
type: 'addition',
|
||||
path: 'pyproject.lock',
|
||||
contents: 'New poetry.lock',
|
||||
},
|
||||
},
|
||||
]);
|
||||
expect(hostRules.find.mock.calls).toHaveLength(3);
|
||||
expect(execSnapshots).toMatchObject([
|
||||
{ cmd: 'poetry update --lock --no-interaction dep1' },
|
||||
]);
|
||||
|
|
|
@ -17,7 +17,9 @@ import { find } from '../../../util/host-rules';
|
|||
import { regEx } from '../../../util/regex';
|
||||
import { Result } from '../../../util/result';
|
||||
import { parse as parseToml } from '../../../util/toml';
|
||||
import { parseUrl } from '../../../util/url';
|
||||
import { PypiDatasource } from '../../datasource/pypi';
|
||||
import { getGoogleAuthTokenRaw } from '../../datasource/util';
|
||||
import type { UpdateArtifact, UpdateArtifactsResult } from '../types';
|
||||
import { Lockfile, PoetrySchemaToml } from './schema';
|
||||
import type { PoetryFile, PoetrySource } from './types';
|
||||
|
@ -101,7 +103,7 @@ function getPoetrySources(content: string, fileName: string): PoetrySource[] {
|
|||
return [];
|
||||
}
|
||||
if (!pyprojectFile.tool?.poetry) {
|
||||
logger.debug(`{$fileName} contains no poetry section`);
|
||||
logger.debug(`${fileName} contains no poetry section`);
|
||||
return [];
|
||||
}
|
||||
|
||||
|
@ -115,20 +117,42 @@ function getPoetrySources(content: string, fileName: string): PoetrySource[] {
|
|||
return sourceArray;
|
||||
}
|
||||
|
||||
function getMatchingHostRule(url: string | undefined): HostRule {
|
||||
async function getMatchingHostRule(url: string | undefined): Promise<HostRule> {
|
||||
const scopedMatch = find({ hostType: PypiDatasource.id, url });
|
||||
return is.nonEmptyObject(scopedMatch) ? scopedMatch : find({ url });
|
||||
const hostRule = is.nonEmptyObject(scopedMatch) ? scopedMatch : find({ url });
|
||||
if (hostRule) {
|
||||
return hostRule;
|
||||
}
|
||||
|
||||
const parsedUrl = parseUrl(url);
|
||||
if (!parsedUrl) {
|
||||
logger.once.debug(`Failed to parse URL ${url}`);
|
||||
return {};
|
||||
}
|
||||
|
||||
if (parsedUrl.hostname.endsWith('.pkg.dev')) {
|
||||
const accessToken = await getGoogleAuthTokenRaw();
|
||||
if (accessToken) {
|
||||
return {
|
||||
username: 'oauth2accesstoken',
|
||||
password: accessToken,
|
||||
};
|
||||
}
|
||||
logger.once.debug(`Could not get Google access token (url=${url})`);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
function getSourceCredentialVars(
|
||||
async function getSourceCredentialVars(
|
||||
pyprojectContent: string,
|
||||
packageFileName: string,
|
||||
): NodeJS.ProcessEnv {
|
||||
): Promise<NodeJS.ProcessEnv> {
|
||||
const poetrySources = getPoetrySources(pyprojectContent, packageFileName);
|
||||
const envVars: NodeJS.ProcessEnv = {};
|
||||
|
||||
for (const source of poetrySources) {
|
||||
const matchingHostRule = getMatchingHostRule(source.url);
|
||||
const matchingHostRule = await getMatchingHostRule(source.url);
|
||||
const formattedSourceName = source.name
|
||||
.replace(regEx(/(\.|-)+/g), '_')
|
||||
.toUpperCase();
|
||||
|
@ -192,7 +216,10 @@ export async function updateArtifacts({
|
|||
config.constraints?.poetry ??
|
||||
getPoetryRequirement(newPackageFileContent, existingLockFileContent);
|
||||
const extraEnv = {
|
||||
...getSourceCredentialVars(newPackageFileContent, packageFileName),
|
||||
...(await getSourceCredentialVars(
|
||||
newPackageFileContent,
|
||||
packageFileName,
|
||||
)),
|
||||
...getGitEnvironmentVariables(['poetry']),
|
||||
PIP_CACHE_DIR: await ensureCacheDir('pip'),
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue