Skip to content

Commit

Permalink
feat(manager/composer): support git-tags hostRules for github.com whe…
Browse files Browse the repository at this point in the history
…n updating artifacts (#18004)

Co-authored-by: Rhys Arkins <rhys@arkins.net>
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
fixes undefined
  • Loading branch information
etremblay committed Jan 13, 2023
1 parent 5917c54 commit e8a5437
Show file tree
Hide file tree
Showing 5 changed files with 420 additions and 5 deletions.
19 changes: 19 additions & 0 deletions docs/usage/getting-started/private-packages.md
Expand Up @@ -179,6 +179,25 @@ The following details the most common/popular manager artifacts updating and how

Any `hostRules` token for `github.com` or `gitlab.com` are found and written out to `COMPOSER_AUTH` in env for Composer to parse.
Any `hostRules` with `hostType=packagist` are also included.
For dependencies on `github.com` without a Packagist server: use a Personal Access Token for `hostRule` with `hostType=git-tags`, do not use an application token.
Avoid adding a `hostRule` with `hostType=github` because:

- it overrides the default Renovate application token for everything else
- it causes unwanted side effects

The repository in `composer.json` should have the `vcs` type with a `https` URL.
For example:

```json
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/organization/private-repository"
}
]
}
```

### gomod

Expand Down
124 changes: 122 additions & 2 deletions lib/modules/manager/composer/artifacts.spec.ts
Expand Up @@ -7,6 +7,7 @@ import * as docker from '../../../util/exec/docker';
import type { StatusResult } from '../../../util/git/types';
import * as hostRules from '../../../util/host-rules';
import * as _datasource from '../../datasource';
import { GitTagsDatasource } from '../../datasource/git-tags';
import { PackagistDatasource } from '../../datasource/packagist';
import type { UpdateArtifactsConfig } from '../types';
import * as composer from '.';
Expand Down Expand Up @@ -112,7 +113,13 @@ describe('modules/manager/composer/artifacts', () => {
hostRules.add({
hostType: 'github',
matchHost: 'api.github.com',
token: 'github-token',
token: 'ghp_github-token',
});
// This rule should not affect the result the Github rule has priority to avoid breaking changes.
hostRules.add({
hostType: GitTagsDatasource.id,
matchHost: 'github.com',
token: 'ghp_git-tags-token',
});
hostRules.add({
hostType: 'gitlab',
Expand Down Expand Up @@ -164,14 +171,127 @@ describe('modules/manager/composer/artifacts', () => {
cwd: '/tmp/github/some/repo',
env: {
COMPOSER_AUTH:
'{"github-oauth":{"github.com":"github-token"},"gitlab-token":{"gitlab.com":"gitlab-token"},"gitlab-domains":["gitlab.com"],"http-basic":{"packagist.renovatebot.com":{"username":"some-username","password":"some-password"},"artifactory.yyyyyyy.com":{"username":"some-other-username","password":"some-other-password"}},"bearer":{"packages-bearer.example.com":"abcdef0123456789"}}',
'{"github-oauth":{"github.com":"ghp_git-tags-token"},' +
'"gitlab-token":{"gitlab.com":"gitlab-token"},' +
'"gitlab-domains":["gitlab.com"],' +
'"http-basic":{' +
'"packagist.renovatebot.com":{"username":"some-username","password":"some-password"},' +
'"artifactory.yyyyyyy.com":{"username":"some-other-username","password":"some-other-password"}' +
'},' +
'"bearer":{"packages-bearer.example.com":"abcdef0123456789"}}',
COMPOSER_CACHE_DIR: '/tmp/renovate/cache/others/composer',
},
},
},
]);
});

it('git-tags hostRule for github.com set github-token in COMPOSER_AUTH', async () => {
hostRules.add({
hostType: GitTagsDatasource.id,
matchHost: 'github.com',
token: 'ghp_token',
});
fs.readLocalFile.mockResolvedValueOnce('{}');
const execSnapshots = mockExecAll();
fs.readLocalFile.mockResolvedValueOnce('{}');
const authConfig = {
...config,
registryUrls: ['https://packagist.renovatebot.com'],
};
git.getRepoStatus.mockResolvedValueOnce(repoStatus);
expect(
await composer.updateArtifacts({
packageFileName: 'composer.json',
updatedDeps: [],
newPackageFileContent: '{}',
config: authConfig,
})
).toBeNull();

expect(execSnapshots).toMatchObject([
{
options: {
env: {
COMPOSER_AUTH: '{"github-oauth":{"github.com":"ghp_token"}}',
},
},
},
]);
});

it('Skip github application access token hostRules in COMPOSER_AUTH', async () => {
hostRules.add({
hostType: 'github',
matchHost: 'api.github.com',
token: 'ghs_token',
});
hostRules.add({
hostType: GitTagsDatasource.id,
matchHost: 'github.com',
token: 'ghp_token',
});
fs.readLocalFile.mockResolvedValueOnce('{}');
const execSnapshots = mockExecAll();
fs.readLocalFile.mockResolvedValueOnce('{}');
const authConfig = {
...config,
registryUrls: ['https://packagist.renovatebot.com'],
};
git.getRepoStatus.mockResolvedValueOnce(repoStatus);
expect(
await composer.updateArtifacts({
packageFileName: 'composer.json',
updatedDeps: [],
newPackageFileContent: '{}',
config: authConfig,
})
).toBeNull();
expect(execSnapshots).toMatchObject([
{
options: {
env: {
COMPOSER_AUTH: '{"github-oauth":{"github.com":"ghp_token"}}',
},
},
},
]);
});

it('github hostRule for github.com with x-access-token set github-token in COMPOSER_AUTH', async () => {
hostRules.add({
hostType: 'github',
matchHost: 'https://api.github.com/',
token: 'x-access-token:ghp_token',
});
fs.readLocalFile.mockResolvedValueOnce('{}');
const execSnapshots = mockExecAll();
fs.readLocalFile.mockResolvedValueOnce('{}');
const authConfig = {
...config,
registryUrls: ['https://packagist.renovatebot.com'],
};
git.getRepoStatus.mockResolvedValueOnce(repoStatus);
expect(
await composer.updateArtifacts({
packageFileName: 'composer.json',
updatedDeps: [],
newPackageFileContent: '{}',
config: authConfig,
})
).toBeNull();

expect(execSnapshots).toMatchObject([
{
options: {
env: {
COMPOSER_AUTH: '{"github-oauth":{"github.com":"ghp_token"}}',
},
},
},
]);
});

it('returns updated composer.lock', async () => {
fs.readLocalFile.mockResolvedValueOnce('{}');
const execSnapshots = mockExecAll();
Expand Down
19 changes: 16 additions & 3 deletions lib/modules/manager/composer/artifacts.ts
Expand Up @@ -18,26 +18,39 @@ import {
import { getRepoStatus } from '../../../util/git';
import * as hostRules from '../../../util/host-rules';
import { regEx } from '../../../util/regex';
import { GitTagsDatasource } from '../../datasource/git-tags';
import { PackagistDatasource } from '../../datasource/packagist';
import type { UpdateArtifact, UpdateArtifactsResult } from '../types';
import type { AuthJson, ComposerLock } from './types';
import {
extractConstraints,
findGithubToken,
getComposerArguments,
getPhpConstraint,
requireComposerDependencyInstallation,
takePersonalAccessTokenIfPossible,
} from './utils';

function getAuthJson(): string | null {
const authJson: AuthJson = {};

const githubCredentials = hostRules.find({
const githubToken = findGithubToken({
hostType: 'github',
url: 'https://api.github.com/',
});
if (githubCredentials?.token) {

const gitTagsGithubToken = findGithubToken({
hostType: GitTagsDatasource.id,
url: 'https://github.com',
});

const selectedGithubToken = takePersonalAccessTokenIfPossible(
githubToken,
gitTagsGithubToken
);
if (selectedGithubToken) {
authJson['github-oauth'] = {
'github.com': githubCredentials.token.replace('x-access-token:', ''),
'github.com': selectedGithubToken,
};
}

Expand Down

0 comments on commit e8a5437

Please sign in to comment.