Skip to content

Commit

Permalink
feat(vcs-host): expect vcs-host scaffolder to return details under th…
Browse files Browse the repository at this point in the history
…e `vcs` results object
  • Loading branch information
travi committed Jul 29, 2024
1 parent ca5fd56 commit 8353d13
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 40 deletions.
21 changes: 11 additions & 10 deletions src/scaffolder.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {reportResults} from '@form8ion/results-reporter';
import {scaffold as scaffoldReadme} from '@form8ion/readme';
import {info} from '@travi/cli-messages';

import {scaffold as scaffoldLanguage, prompt as promptForLanguageDetails} from './language/index.js';
import {prompt as promptForLanguageDetails, scaffold as scaffoldLanguage} from './language/index.js';
import {initialize as scaffoldGit, scaffold as liftGit} from './vcs/git/git.js';
import {scaffold as scaffoldLicense} from './license/index.js';
import {scaffold as scaffoldVcsHost} from './vcs/host/index.js';
Expand Down Expand Up @@ -56,7 +56,7 @@ export async function scaffold(options) {
])
: [];

const gitResults = gitRepo && await liftGit({projectRoot, origin: vcsHostResults});
const gitResults = gitRepo && await liftGit({projectRoot, vcs: vcsHostResults.vcs});

const {[questionNames.PROJECT_LANGUAGE]: projectLanguage} = await promptForLanguageDetails(languages, decisions);

Expand All @@ -66,9 +66,15 @@ export async function scaffold(options) {
{projectRoot, projectName, vcs, visibility, license: chosenLicense || 'UNLICENSED', description}
);

const contributors = [license, language, dependencyUpdaterResults, contributing, gitResults].filter(Boolean);
const mergedResults = deepmerge.all([
license,
language,
dependencyUpdaterResults,
contributing,
gitResults
].filter(Boolean));

await lift({projectRoot, vcs, results: deepmerge.all(contributors), enhancers: {...dependencyUpdaters, ...vcsHosts}});
await lift({projectRoot, vcs, results: mergedResults, enhancers: {...dependencyUpdaters, ...vcsHosts}});

if (language && language.verificationCommand) {
info('Verifying the generated project');
Expand All @@ -78,10 +84,5 @@ export async function scaffold(options) {
await subprocess;
}

const contributedTasks = contributors
.map(contributor => contributor.nextSteps)
.filter(Boolean)
.reduce((acc, contributedNextSteps) => ([...acc, ...contributedNextSteps]), []);

reportResults({nextSteps: contributedTasks});
reportResults({nextSteps: mergedResults.nextSteps});
}
70 changes: 50 additions & 20 deletions src/scaffolder.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import any from '@travi/any';
import {when} from 'jest-when';

import {scaffold as liftGit, initialize as scaffoldGit} from './vcs/git/git.js';
import * as vcsHostScaffolder from './vcs/host/scaffolder.js';
import {scaffold as scaffoldVcsHost} from './vcs/host/index.js';
import * as licenseScaffolder from './license/scaffolder.js';
import scaffoldLanguage from './language/scaffolder.js';
import * as languagePrompt from './language/prompt.js';
Expand All @@ -27,7 +27,7 @@ vi.mock('@form8ion/execa-wrapper');
vi.mock('@form8ion/results-reporter');
vi.mock('./readme');
vi.mock('./vcs/git/git.js');
vi.mock('./vcs/host/scaffolder');
vi.mock('./vcs/host/index.js');
vi.mock('./license/scaffolder');
vi.mock('./language/scaffolder');
vi.mock('./language/prompt');
Expand All @@ -53,6 +53,7 @@ describe('project scaffolder', () => {
const documentation = any.simpleObject();
const vcs = any.simpleObject();
const vcsOriginDetails = any.simpleObject();
const vcsHostResults = {...any.simpleObject(), vcs: vcsOriginDetails};
const tags = any.listOf(any.word);
const visibility = any.word();
const vcsIgnore = any.simpleObject();
Expand Down Expand Up @@ -117,7 +118,7 @@ describe('project scaffolder', () => {
when(licenseScaffolder.default)
.calledWith({projectRoot: projectPath, license, copyright})
.mockResolvedValue(licenseResults);
when(vcsHostScaffolder.default)
when(scaffoldVcsHost)
.calledWith(
vcsHosts,
{
Expand All @@ -127,7 +128,7 @@ describe('project scaffolder', () => {
visibility
}
)
.mockResolvedValue(vcsOriginDetails);
.mockResolvedValue(vcsHostResults);
scaffoldLanguage.mockResolvedValue(languageResults);
when(dependencyUpdaterScaffolder.default)
.calledWith(dependencyUpdaters, decisions, {projectRoot: projectPath, vcs})
Expand All @@ -138,7 +139,7 @@ describe('project scaffolder', () => {

expect(liftGit).toHaveBeenCalledWith({
projectRoot: projectPath,
origin: vcsOriginDetails
vcs: vcsOriginDetails
});
expect(scaffoldReadme).toHaveBeenCalledWith({projectName, projectRoot: projectPath, description});
expect(dependencyUpdaterScaffolder.default).toHaveBeenCalledWith(
Expand Down Expand Up @@ -173,7 +174,20 @@ describe('project scaffolder', () => {
[coreQuestionNames.PROJECT_NAME]: projectName,
[questionNames.GIT_REPO]: gitRepoShouldBeInitialized
});

when(scaffoldGit).mockResolvedValue(vcs);
languagePrompt.default.mockResolvedValue({});
when(scaffoldVcsHost)
.calledWith(
{},
{
...vcs,
projectRoot: projectPath,
description: undefined,
visibility: undefined
}
)
.mockResolvedValue(vcsHostResults);

await scaffold();

Expand All @@ -184,9 +198,10 @@ describe('project scaffolder', () => {
it('should consider each option except the plugins map optional', async () => {
const emptyOptions = {};
when(optionsValidator.validate).calledWith(emptyOptions).mockReturnValue({plugins: {}});
when(prompts.promptForBaseDetails).calledWith(projectPath, undefined, undefined).mockResolvedValue({});
when(prompts.promptForBaseDetails).calledWith(projectPath, undefined).mockResolvedValue({});
languagePrompt.default.mockResolvedValue({});
scaffoldGit.mockResolvedValue({});
scaffoldVcsHost.mockResolvedValue(vcsHostResults);

await scaffold(emptyOptions);
});
Expand All @@ -213,18 +228,36 @@ describe('project scaffolder', () => {
contribution: any.simpleObject()
};
const languageResults = {badges: languageBadges, vcsIgnore, documentation};
when(optionsValidator.validate).calledWith(options).mockReturnValue({plugins: {vcsHosts}});
when(prompts.promptForBaseDetails)
.calledWith(projectPath, undefined, undefined)
.mockResolvedValue({[coreQuestionNames.VISIBILITY]: visibility});
.calledWith(projectPath, undefined)
.mockResolvedValue({
[coreQuestionNames.DESCRIPTION]: description,
[questionNames.GIT_REPO]: true,
[coreQuestionNames.PROJECT_NAME]: projectName,
[coreQuestionNames.VISIBILITY]: visibility
});
when(scaffoldContributing).calledWith({visibility}).mockReturnValue({badges: contributingBadges});
scaffoldLanguage.mockResolvedValue(languageResults);
vcsHostScaffolder.default.mockResolvedValue(vcsOriginDetails);
when(scaffoldVcsHost)
.calledWith(
vcsHosts,
{
...vcs,
projectRoot: projectPath,
description,
visibility
}
)
.mockResolvedValue(vcsHostResults);
dependencyUpdaterScaffolder.default.mockResolvedValue({badges: dependencyUpdaterBadges});
licenseScaffolder.default.mockResolvedValue({badges: licenseBadges});
languagePrompt.default.mockResolvedValue({});
when(scaffoldGit).mockResolvedValue(vcs);

await scaffold(options);

expect(liftGit).toHaveBeenCalledWith({projectRoot: projectPath, origin: vcsOriginDetails});
expect(liftGit).toHaveBeenCalledWith({projectRoot: projectPath, vcs: vcsOriginDetails});
expect(scaffoldReadme).toHaveBeenCalledWith({projectName, projectRoot: projectPath, description});
});

Expand All @@ -238,7 +271,7 @@ describe('project scaffolder', () => {
await scaffold(options);

expect(liftGit).not.toHaveBeenCalled();
expect(vcsHostScaffolder.default).not.toHaveBeenCalled();
expect(scaffoldVcsHost).not.toHaveBeenCalled();
expect(dependencyUpdaterScaffolder.default).not.toHaveBeenCalled();
});

Expand Down Expand Up @@ -287,26 +320,23 @@ describe('project scaffolder', () => {
vcs,
description
}).mockResolvedValue(languageResults);
when(vcsHostScaffolder.default).calledWith(
when(scaffoldVcsHost).calledWith(
vcsHosts,
{
...vcs,
projectRoot: projectPath,
description,
homepage,
visibility,
nextSteps: languageNextSteps,
tags
visibility
}
).mockResolvedValue(vcsOriginDetails);
).mockResolvedValue(vcsHostResults);
when(execa).calledWith(verificationCommand, {shell: true}).mockReturnValue({stdout: {pipe: execaPipe}});
dependencyUpdaterScaffolder.default.mockResolvedValue({});
licenseScaffolder.default.mockResolvedValue({});
scaffoldContributing.mockResolvedValue({});

await scaffold(options);

expect(liftGit).toHaveBeenCalledWith({projectRoot: projectPath, origin: vcsOriginDetails});
expect(liftGit).toHaveBeenCalledWith({projectRoot: projectPath, vcs: vcsOriginDetails});
expect(scaffoldReadme).toHaveBeenCalledWith({projectName, projectRoot: projectPath, description});
expect(execaPipe).toHaveBeenCalledWith(process.stdout);
expect(resultsReporter.reportResults).toHaveBeenCalledWith({nextSteps: [...languageNextSteps, ...gitNextSteps]});
Expand All @@ -327,15 +357,15 @@ describe('project scaffolder', () => {
when(languagePrompt.default)
.calledWith(languages, decisions)
.mockResolvedValue({[questionNames.PROJECT_LANGUAGE]: projectLanguage});
vcsHostScaffolder.default.mockResolvedValue(vcsOriginDetails);
scaffoldVcsHost.mockResolvedValue(vcsHostResults);
scaffoldLanguage.mockResolvedValue({});
dependencyUpdaterScaffolder.default.mockResolvedValue({});
licenseScaffolder.default.mockResolvedValue({});
scaffoldContributing.mockResolvedValue({});

await scaffold(options);

expect(liftGit).toHaveBeenCalledWith({projectRoot: projectPath, origin: vcsOriginDetails});
expect(liftGit).toHaveBeenCalledWith({projectRoot: projectPath, vcs: vcsOriginDetails});
expect(scaffoldReadme).toHaveBeenCalledWith({projectName, projectRoot: projectPath, description});
expect(execa).not.toHaveBeenCalled();
});
Expand Down
12 changes: 6 additions & 6 deletions src/vcs/git/git.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ async function getExistingRemotes(git) {
}
}

async function defineRemoteOrigin(projectRoot, origin) {
async function defineRemoteOrigin(projectRoot, vcs) {
const git = simpleGit({baseDir: projectRoot});
const existingRemotes = await getExistingRemotes(git);

Expand All @@ -28,10 +28,10 @@ async function defineRemoteOrigin(projectRoot, origin) {
return {nextSteps: []};
}

if (origin.sshUrl) {
info(`Setting remote origin to ${origin.sshUrl}`, {level: 'secondary'});
if (vcs.sshUrl) {
info(`Setting remote origin to ${vcs.sshUrl}`, {level: 'secondary'});

await git.addRemote('origin', origin.sshUrl);
await git.addRemote('origin', vcs.sshUrl);

// info('Setting the local `master` branch to track `origin/master`');
//
Expand Down Expand Up @@ -82,10 +82,10 @@ export async function initialize(
return undefined;
}

export async function scaffold({projectRoot, origin}) {
export async function scaffold({projectRoot, vcs}) {
info('Finishing Git Configuration');

const remoteOriginResults = await defineRemoteOrigin(projectRoot, origin);
const remoteOriginResults = await defineRemoteOrigin(projectRoot, vcs);

return {nextSteps: [{summary: 'Commit scaffolded files'}, ...remoteOriginResults.nextSteps]};
}
4 changes: 2 additions & 2 deletions src/vcs/git/git.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ describe('git', () => {
it('should scaffold the git repo', async () => {
listRemote.mockRejectedValue(new Error('fatal: No remote configured to list refs from.\n'));

const result = await scaffold({projectRoot, origin: {}, results});
const result = await scaffold({projectRoot, vcs: {}, results});

expect(result.nextSteps).toEqual([{summary: 'Commit scaffolded files'}]);
});
Expand All @@ -109,7 +109,7 @@ describe('git', () => {
// gitBranch.lookup.withArgs(repository, 'master', gitBranch.BRANCH.LOCAL).resolves(branch);
listRemote.mockResolvedValue(any.listOf(any.word));

const result = await scaffold({projectRoot, origin: {sshUrl}});
const result = await scaffold({projectRoot, vcs: {sshUrl}});

expect(addRemote).toHaveBeenCalledWith('origin', sshUrl);
expect(result.nextSteps).toEqual([
Expand Down
2 changes: 1 addition & 1 deletion test/integration/features/step_definitions/common-steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ When(/^the project is scaffolded$/, async function () {
...vcsHost && {
vcsHosts: {
[vcsHost]: {
scaffold: ({name, owner}) => ({sshUrl: this.remoteOriginUrl, name, owner}),
scaffold: ({name, owner}) => ({vcs: {sshUrl: this.remoteOriginUrl, name, owner}}),
prompt: () => undefined
}
}
Expand Down
2 changes: 1 addition & 1 deletion vitest.config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import {defineConfig} from 'vitest/config';

export default defineConfig({test: {globals: true}});
export default defineConfig({test: {globals: true, restoreMocks: true}});

0 comments on commit 8353d13

Please sign in to comment.