Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(create-gatsby): Improve install (#28318) #28406

Merged
merged 1 commit into from
Dec 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 21 additions & 20 deletions packages/create-gatsby/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ import Enquirer from "enquirer"
import cmses from "./cmses.json"
import styles from "./styles.json"
import features from "./features.json"
import { initStarter, getPackageManager } from "./init-starter"
import { initStarter, getPackageManager, gitSetup } from "./init-starter"
import { installPlugins } from "./install-plugins"
import c from "ansi-colors"
import path from "path"
import fs from "fs"
import { plugin } from "./components/plugin"
import { makePluginConfigQuestions } from "./plugin-options-form"
import { center, rule, wrap } from "./components/utils"
import { center, wrap } from "./components/utils"
import { stripIndent } from "common-tags"
import { trackCli } from "./tracking"
import crypto from "crypto"
import { reporter } from "./reporter"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was merge conflict here due to neighbouring

import { setSiteMetadata } from "./site-metadata"

added by #28324 which is not backported and was merged before this PR


const sha256 = (str: string): string =>
crypto.createHash(`sha256`).update(str).digest(`hex`)
Expand Down Expand Up @@ -50,6 +51,7 @@ const makeChoices = (
export const validateProjectName = async (
value: string
): Promise<string | boolean> => {
value = value.trim()
if (INVALID_FILENAMES.test(value)) {
return `The destination "${value}" is not a valid filename. Please try again, avoiding special characters.`
}
Expand Down Expand Up @@ -138,9 +140,9 @@ export async function run(): Promise<void> {

const { version } = require(`../package.json`)

console.log(c.grey(`create-gatsby version ${version}`))
reporter.info(c.grey(`create-gatsby version ${version}`))

console.log(
reporter.info(
`


Expand All @@ -150,23 +152,23 @@ ${center(c.blueBright.bold.underline(`Welcome to Gatsby!`))}
`
)

console.log(
reporter.info(
wrap(
`This command will generate a new Gatsby site for you in ${c.bold(
process.cwd()
)} with the setup you select. ${c.white.bold(
`Let's answer some questions:\n`
`Let's answer some questions:\n\n`
)}`,
process.stdout.columns
)
)
console.log(``)

const enquirer = new Enquirer<IAnswers>()

enquirer.use(plugin)

const data = await enquirer.prompt(questions)
data.project = data.project.trim()

trackCli(`CREATE_GATSBY_SELECT_OPTION`, {
name: `project_name`,
Expand Down Expand Up @@ -259,7 +261,7 @@ ${center(c.blueBright.bold.underline(`Welcome to Gatsby!`))}

const config = makePluginConfigQuestions(plugins)
if (config.length) {
console.log(
reporter.info(
`\nGreat! A few of the selections you made need to be configured. Please fill in the options for each plugin now:\n`
)

Expand All @@ -273,7 +275,7 @@ ${center(c.blueBright.bold.underline(`Welcome to Gatsby!`))}
trackCli(`CREATE_GATSBY_SET_PLUGINS_STOP`)
}

console.log(`
reporter.info(`

${c.bold(`Thanks! Here's what we'll now do:`)}

Expand All @@ -291,42 +293,41 @@ ${c.bold(`Thanks! Here's what we'll now do:`)}
if (!confirm) {
trackCli(`CREATE_GATSBY_CANCEL`)

console.log(`OK, bye!`)
reporter.info(`OK, bye!`)
return
}

await initStarter(DEFAULT_STARTER, data.project, packages.map(removeKey))

console.log(
c.green(c.symbols.check) + ` Created site in ` + c.green(data.project)
)
reporter.success(`Created site in ${c.green(data.project)}`)

if (plugins.length) {
console.log(c.bold(`${w(`🔌 `)}Installing plugins...`))
reporter.info(`${w(`🔌 `)}Setting-up plugins...`)
await installPlugins(plugins, pluginConfig, path.resolve(data.project), [])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was merge conflict here due to change from path.resolve(data.project) to fullPath added by #28324 which is not backported and was merged before this PR

}

const pm = await getPackageManager()
await gitSetup(data.project)

const pm = await getPackageManager()
const runCommand = pm === `npm` ? `npm run` : `yarn`

console.log(
reporter.info(
stripIndent`
${w(`🎉 `)}Your new Gatsby site ${c.bold(
data.project
)} has been successfully bootstrapped
)} has been successfully created
at ${c.bold(path.resolve(data.project))}.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was merge conflict here due to change from path.resolve(data.project) to fullPath added by #28324 which is not backported and was merged before this PR

`
)
console.log(`Start by going to the directory with\n
reporter.info(`Start by going to the directory with\n
${c.magenta(`cd ${data.project}`)}
`)

console.log(`Start the local development server with\n
reporter.info(`Start the local development server with\n
${c.magenta(`${runCommand} develop`)}
`)

console.log(`See all commands at\n
reporter.info(`See all commands at\n
${c.blueBright(`https://www.gatsbyjs.com/docs/gatsby-cli/`)}
`)

Expand Down
94 changes: 68 additions & 26 deletions packages/create-gatsby/src/init-starter.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,40 @@
import { execSync } from "child_process"
import execa from "execa"
import execa, { Options } from "execa"
import fs from "fs-extra"
import path from "path"
import { reporter } from "./reporter"
import { spin } from "tiny-spin"
import { getConfigStore } from "./get-config-store"
type PackageManager = "yarn" | "npm"
import c from "ansi-colors"

const packageMangerConfigKey = `cli.packageManager`
const packageManagerConfigKey = `cli.packageManager`

const kebabify = (str: string): string =>
str
.replace(/([a-z])([A-Z])/g, `$1-$2`)
.replace(/[^a-zA-Z]+/g, `-`)
.toLowerCase()

export const getPackageManager = (): PackageManager =>
getConfigStore().get(packageMangerConfigKey)
getConfigStore().get(packageManagerConfigKey)

export const setPackageManager = (packageManager: PackageManager): void => {
getConfigStore().set(packageMangerConfigKey, packageManager)
getConfigStore().set(packageManagerConfigKey, packageManager)
}

const ESC = `\u001b`

export const clearLine = (count = 1): Promise<boolean> =>
new Promise(resolve => {
// First move the cursor up one line...
process.stderr.moveCursor(0, -count, () => {
// ... then clear that line. This is the ANSI escape sequence for "clear whole line"
// List of escape sequences: http://ascii-table.com/ansi-escape-sequences.php
process.stderr.write(`${ESC}[2K`)
resolve()
})
})
// Checks the existence of yarn package
// We use yarnpkg instead of yarn to avoid conflict with Hadoop yarn
// Refer to https://github.com/yarnpkg/yarn/issues/673
Expand All @@ -31,19 +50,15 @@ const checkForYarn = (): boolean => {
// Initialize newly cloned directory as a git repo
const gitInit = async (
rootPath: string
): Promise<execa.ExecaReturnBase<string>> => {
reporter.info(`Initialising git in ${rootPath}`)

return await execa(`git`, [`init`], { cwd: rootPath })
}
): Promise<execa.ExecaReturnBase<string>> =>
await execa(`git`, [`init`], { cwd: rootPath })

// Create a .gitignore file if it is missing in the new directory
const maybeCreateGitIgnore = async (rootPath: string): Promise<void> => {
if (fs.existsSync(path.join(rootPath, `.gitignore`))) {
return
}

reporter.info(`Creating minimal .gitignore in ${rootPath}`)
await fs.writeFile(
path.join(rootPath, `.gitignore`),
`.cache\nnode_modules\npublic\n`
Expand All @@ -52,8 +67,6 @@ const maybeCreateGitIgnore = async (rootPath: string): Promise<void> => {

// Create an initial git commit in the new directory
const createInitialGitCommit = async (rootPath: string): Promise<void> => {
reporter.info(`Create initial git commit in ${rootPath}`)

await execa(`git`, [`add`, `-A`], { cwd: rootPath })
// use execSync instead of spawn to handle git clients using
// pgp signatures (with password)
Expand All @@ -68,21 +81,41 @@ const createInitialGitCommit = async (rootPath: string): Promise<void> => {
}
}

const setNameInPackage = async (
sitePath: string,
name: string
): Promise<void> => {
const packageJsonPath = path.join(sitePath, `package.json`)
const packageJson = await fs.readJSON(packageJsonPath)
packageJson.name = kebabify(name)
packageJson.description = `My Gatsby site`
try {
const result = await execa(`git`, [`config`, `user.name`])
if (result.failed) {
delete packageJson.author
} else {
packageJson.author = result.stdout
}
} catch (e) {
delete packageJson.author
}

await fs.writeJSON(packageJsonPath, packageJson)
}

// Executes `npm install` or `yarn install` in rootPath.
const install = async (
rootPath: string,
packages: Array<string>
): Promise<void> => {
const prevDir = process.cwd()

let stop = spin(`Installing packages...`)
reporter.info(`${c.blueBright(c.symbols.pointer)} Installing Gatsby...`)

process.chdir(rootPath)

const npmConfigUserAgent = process.env.npm_config_user_agent

const silent = `--silent`

try {
if (!getPackageManager()) {
if (npmConfigUserAgent?.includes(`yarn`)) {
Expand All @@ -91,25 +124,33 @@ const install = async (
setPackageManager(`npm`)
}
}
const options: Options = {
stderr: `inherit`,
}

const config = [`--loglevel`, `error`, `--color`, `always`]

if (getPackageManager() === `yarn` && checkForYarn()) {
await fs.remove(`package-lock.json`)
const args = packages.length ? [`add`, silent, ...packages] : [silent]
await execa(`yarnpkg`, args)
const args = packages.length
? [`add`, `--silent`, ...packages]
: [`--silent`]
await execa(`yarnpkg`, args, options)
} else {
await fs.remove(`yarn.lock`)

await execa(`npm`, [`install`, silent])
stop()
stop = spin(`Installing plugins...`)
await execa(`npm`, [`install`, silent, ...packages])
stop()
await execa(`npm`, [`install`, ...config], options)
await clearLine()
reporter.success(`Installed Gatsby`)
reporter.info(`${c.blueBright(c.symbols.pointer)} Installing plugins...`)
await execa(`npm`, [`install`, ...config, ...packages], options)
await clearLine()
reporter.success(`Installed plugins`)
}
} catch (e) {
reporter.panic(e.message)
} finally {
process.chdir(prevDir)
stop()
reporter.success(`Installed packages`)
}
}

Expand Down Expand Up @@ -143,7 +184,7 @@ const clone = async (
await fs.remove(path.join(rootPath, `.git`))
}

async function gitSetup(rootPath: string): Promise<void> {
export async function gitSetup(rootPath: string): Promise<void> {
await gitInit(rootPath)
await maybeCreateGitIgnore(rootPath)
await createInitialGitCommit(rootPath)
Expand All @@ -161,8 +202,9 @@ export async function initStarter(

await clone(starter, sitePath)

await setNameInPackage(sitePath, rootPath)

await install(rootPath, packages)

await gitSetup(rootPath)
// trackCli(`NEW_PROJECT_END`);
}