Skip to content

Commit

Permalink
fix(create-gatsby): Improve install (#28318)
Browse files Browse the repository at this point in the history
(cherry picked from commit 4fbded2)
  • Loading branch information
ascorbic authored and pieh committed Dec 1, 2020
1 parent e444a55 commit a116c4b
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 46 deletions.
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"

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), [])
}

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))}.
`
)
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`);
}

0 comments on commit a116c4b

Please sign in to comment.