Skip to content

Commit 3b1194d

Browse files
committed
feat(existing-vcs): handle self-hosted vcs hosts for existing remote details
1 parent 2cc6b8a commit 3b1194d

File tree

9 files changed

+112
-32
lines changed

9 files changed

+112
-32
lines changed

package-lock.json

Lines changed: 64 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
"deepmerge": "^4.2.2",
7373
"execa": "^9.5.1",
7474
"filedirname": "^3.0.0",
75-
"hosted-git-info": "^8.0.0",
75+
"git-url-parse": "^16.1.0",
7676
"joi": "^17.1.1",
7777
"mustache": "4.2.0",
7878
"simple-git": "^3.16.0",

src/vcs/git/remotes.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {simpleGit} from 'simple-git';
2-
import hostedGitInfo from 'hosted-git-info';
2+
import parseGitUrl from 'git-url-parse';
33
import {warn} from '@travi/cli-messages';
44

55
async function getExistingRemotes(git) {
@@ -17,9 +17,9 @@ async function getExistingRemotes(git) {
1717
export async function determineExistingVcsDetails({projectRoot}) {
1818
const git = simpleGit({baseDir: projectRoot});
1919
const remoteOrigin = await git.remote(['get-url', 'origin']);
20-
const {user, project, type} = hostedGitInfo.fromUrl(remoteOrigin);
20+
const {owner, name, host} = parseGitUrl(remoteOrigin.trimEnd());
2121

22-
return {vcs: {owner: user, name: project, host: type}};
22+
return {vcs: {owner, name, host: 'github.com' === host ? 'github' : host}};
2323
}
2424

2525
export async function defineRemoteOrigin(projectRoot, sshUrl) {

src/vcs/git/remotes.test.js

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,54 @@
11
import {simpleGit} from 'simple-git';
2-
import hostedGitInfo from 'hosted-git-info';
2+
import parseGitUrl from 'git-url-parse';
33

4-
import {describe, vi, it, expect} from 'vitest';
4+
import {describe, vi, it, expect, beforeEach} from 'vitest';
55
import {when} from 'vitest-when';
66
import any from '@travi/any';
77

88
import {determineExistingVcsDetails, defineRemoteOrigin} from './remotes.js';
99

1010
vi.mock('simple-git');
11-
vi.mock('hosted-git-info');
11+
vi.mock('git-url-parse');
1212

1313
describe('Git remote', () => {
1414
const projectRoot = any.string();
1515

1616
describe('determine', () => {
17+
const remote = vi.fn();
18+
const remoteOrigin = any.url();
19+
const repoName = any.word();
20+
const vcsHostAccount = any.word();
21+
22+
beforeEach(() => {
23+
when(simpleGit).calledWith({baseDir: projectRoot}).thenReturn({remote});
24+
});
25+
1726
it('should determine existing vcs details from the remote origin definition of the local repository', async () => {
18-
const remote = vi.fn();
19-
const remoteOrigin = any.url();
20-
const repoName = any.word();
2127
const vcsHost = `F${any.word()})O${any.word()}O`;
22-
const vcsHostAccount = any.word();
23-
when(simpleGit).calledWith({baseDir: projectRoot}).thenReturn({remote});
24-
when(remote).calledWith(['get-url', 'origin']).thenResolve(remoteOrigin);
25-
when(hostedGitInfo.fromUrl)
28+
when(remote).calledWith(['get-url', 'origin']).thenResolve(`${remoteOrigin}\n`);
29+
when(parseGitUrl)
2630
.calledWith(remoteOrigin)
27-
.thenReturn({user: vcsHostAccount, project: repoName, type: vcsHost.toLowerCase()});
31+
.thenReturn({owner: vcsHostAccount, name: repoName, host: vcsHost.toLowerCase()});
2832

2933
const {vcs: hostDetails} = await determineExistingVcsDetails({projectRoot});
3034

3135
expect(hostDetails).toEqual({host: vcsHost.toLowerCase(), owner: vcsHostAccount, name: repoName});
3236
});
37+
38+
it(
39+
'should return `github` when the host is determined to be `github.com` until that can be a breaking change',
40+
async () => {
41+
when(simpleGit).calledWith({baseDir: projectRoot}).thenReturn({remote});
42+
when(remote).calledWith(['get-url', 'origin']).thenResolve(`${remoteOrigin}\n`);
43+
when(parseGitUrl)
44+
.calledWith(remoteOrigin)
45+
.thenReturn({owner: vcsHostAccount, name: repoName, host: 'github.com'});
46+
47+
const {vcs: hostDetails} = await determineExistingVcsDetails({projectRoot});
48+
49+
expect(hostDetails).toEqual({host: 'github', owner: vcsHostAccount, name: repoName});
50+
}
51+
);
3352
});
3453

3554
describe('define', () => {

src/vcs/scaffolder.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export default async function scaffoldVcs({projectRoot, projectName, decisions,
1010
if (await alreadyVersionedByGit({projectRoot})) {
1111
info('Git repository already exists');
1212

13-
return {vcs: await determineExistingVcsDetails({projectRoot})};
13+
return determineExistingVcsDetails({projectRoot});
1414
}
1515

1616
const [{vcs: {host, owner, name, sshUrl}}] = await Promise.all([

src/vcs/scaffolder.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ describe('vcs scaffolder', () => {
4949
when(alreadyVersionedByGit).calledWith({projectRoot}).thenResolve(true);
5050
when(determineExistingVcsDetails).calledWith({projectRoot}).thenResolve(existingVcsDetails);
5151

52-
expect(await scaffoldVcs({projectRoot, decisions})).toEqual({vcs: existingVcsDetails});
52+
expect(await scaffoldVcs({projectRoot, decisions})).toEqual(existingVcsDetails);
5353
});
5454

5555
it('should not scaffold a repository or vcs host details when a repository should not be created', async () => {

test/integration/features/step_definitions/common-steps.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import stubbedFs from 'mock-fs';
88
import {Before, After, Given, When, setWorldConstructor} from '@cucumber/cucumber';
99
import any from '@travi/any';
1010
import * as td from 'testdouble';
11+
import {assert} from 'chai';
1112

1213
import {World} from '../support/world.mjs';
1314

@@ -22,6 +23,7 @@ const stubbedNodeModules = stubbedFs.load(resolve(...projectPath, 'node_modules'
2223

2324
Before({timeout: 20 * 1000}, async function () {
2425
this.projectRoot = process.cwd();
26+
this.projectName = 'project-name';
2527
this.git = await td.replaceEsm('simple-git');
2628

2729
// eslint-disable-next-line import/no-extraneous-dependencies,import/no-unresolved
@@ -49,7 +51,6 @@ When(/^the project is scaffolded$/, async function () {
4951
const chosenLanguage = this.getAnswerFor(questionNames.PROJECT_LANGUAGE) || 'Other';
5052
const vcsHost = this.getAnswerFor(questionNames.REPO_HOST);
5153

52-
this.projectName = 'project-name';
5354
this.projectDescription = any.sentence();
5455
this.projectHomepage = any.url();
5556

@@ -65,9 +66,16 @@ When(/^the project is scaffolded$/, async function () {
6566
languages: {
6667
...'Other' !== chosenLanguage && {
6768
[chosenLanguage]: {
68-
scaffold: ({projectName}) => {
69+
scaffold: ({projectName, vcs}) => {
6970
info(`Scaffolding ${chosenLanguage} language details for ${projectName}`);
7071

72+
if (repoShouldBeCreated && ((vcsHost && 'Other' !== vcsHost) || this.existingVcsHost)) {
73+
assert.equal(vcs.name, this.projectName);
74+
if ('GitHub' === this.existingVcsHost) {
75+
assert.equal(vcs.host, 'github');
76+
}
77+
}
78+
7179
return this.languageScaffolderResults;
7280
},
7381
test: ({projectRoot}) => {

test/integration/features/step_definitions/vcs/git-steps.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Given(/^the project should not be versioned in git$/, async function () {
3232
Given('the project root is already initialized as a git repository', async function () {
3333
this.existingVcsIgnoredFiles = any.listOf(any.word);
3434
this.existingVcsIgnoredDirectories = any.listOf(any.word);
35+
this.existingVcsHost = 'GitHub';
3536

3637
await fs.mkdir(`${process.cwd()}/.git`, {recursive: true});
3738
await fs.writeFile(

test/integration/features/step_definitions/vcs/vcs-host-steps.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Given('the repository is hosted on {string}', async function (host) {
1616
this.repoHost = host;
1717
this.vcsOwner = any.word();
1818
this.vcsName = any.word();
19+
this.setAnswerFor(questionNames.REPO_HOST, this.repoHost);
1920
});
2021

2122
Then('the project repository is hosted on the chosen host', async function () {

0 commit comments

Comments
 (0)