Skip to content

Commit

Permalink
feat(gatsby-cli): enable set packagemanager (#26856)
Browse files Browse the repository at this point in the history
* Address configuration issues related to package manager selection

* fix linting

* use the right cli

* clean up yargs

* change console log

* missing comma

* find the eslint bug

* think it was this

* add everything back

* change logic a bit, shouldn't also set telemetry

* add whitespace

* ignore TS error for the moment to validate the logic

* switch order of validate script commands

* Update packages/gatsby-cli/src/init-starter.ts

Co-authored-by: Ward Peeters <ward@coding-tech.com>

* use pathExists

* use pathExists

* We want to keep the lock files

* set package manager to yarn for gatsby new tests

* fix tests and remove yarn.lock from official starters

* might be a typescript issue

* use positional arguments instead

* adjust tests

* fix plugin command top level error

* run in gatsby project

* make it a one off test like feedback

* update links to .com and rename as options

* remove unused prompt code

* Allow for package-manager as key

* decouple publish starters script from CLI version by keeping yarn import

* Update scripts/publish-starters.sh

Co-authored-by: Ward Peeters <ward@coding-tech.com>

Co-authored-by: Laurie Barth <laurie@lauriesrklaptop.lan>
Co-authored-by: Ward Peeters <ward@coding-tech.com>
Co-authored-by: Laurie Barth <laurie@LauriesrkLaptop.fios-router.home>
Co-authored-by: gatsbybot <mathews.kyle+gatsbybot@gmail.com>
  • Loading branch information
5 people committed Sep 18, 2020
1 parent 390ae17 commit 5658b87
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 87 deletions.
9 changes: 8 additions & 1 deletion integration-tests/gatsby-cli/__tests__/new.js
Expand Up @@ -2,6 +2,7 @@ import { GatsbyCLI } from "../test-helpers"
import * as fs from "fs-extra"
import execa from "execa"
import { join } from "path"
import { getConfigStore } from "gatsby-core-utils"

const MAX_TIMEOUT = 30000
jest.setTimeout(MAX_TIMEOUT)
Expand All @@ -13,12 +14,18 @@ const clean = dir => execa(`yarn`, ["del-cli", dir])
describe(`gatsby new`, () => {
// make folder for us to create sites into
const dir = join(__dirname, "../execution-folder")
const originalPackageManager = getConfigStore().get("cli.packageManager")

beforeAll(async () => {
await clean(dir)
await fs.ensureDir(dir)
GatsbyCLI.from(cwd).invoke([`options`, `set`, `pm`, `yarn`])
})

afterAll(() => clean(dir))
afterAll(async () => {
GatsbyCLI.from(cwd).invoke([`options`, `set`,`pm`, originalPackageManager])
await clean(dir)
})

it(`a default starter creates a gatsby site`, () => {
const [code, logs] = GatsbyCLI.from(cwd).invoke([`new`, `gatsby-default`])
Expand Down
14 changes: 14 additions & 0 deletions integration-tests/gatsby-cli/__tests__/options.js
@@ -0,0 +1,14 @@
import { GatsbyCLI } from "../test-helpers"

const MAX_TIMEOUT = 2147483647
jest.setTimeout(MAX_TIMEOUT)

describe(`gatsby options`, () => {
it(`Prints the options`, () => {
const [status, logs] = GatsbyCLI.from(`gatsby-sites/gatsby-build`).invoke(`options`)

logs.should.contain(`Package Manager`)
logs.should.contain(`Telemetry enabled`)
expect(status).toBe(0)
})
})
145 changes: 104 additions & 41 deletions packages/gatsby-cli/src/create-cli.ts
Expand Up @@ -7,10 +7,17 @@ import { getLocalGatsbyVersion } from "./util/version"
import envinfo from "envinfo"
import { sync as existsSync } from "fs-exists-cached"
import clipboardy from "clipboardy"
import { trackCli, setDefaultTags, setTelemetryEnabled } from "gatsby-telemetry"
import {
trackCli,
setDefaultTags,
setTelemetryEnabled,
isTrackingEnabled,
} from "gatsby-telemetry"
import { initStarter } from "./init-starter"
import { recipesHandler } from "./recipes"
import { startGraphQLServer } from "gatsby-recipes"
import { getPackageManager, setPackageManager } from "./util/package-manager"
import reporter from "../lib/reporter"

const handlerP = (fn: Function) => (...args: Array<unknown>): void => {
Promise.resolve(fn(...args)).then(
Expand Down Expand Up @@ -144,24 +151,24 @@ function buildLocalCommands(cli: yargs.Argv, isLocalSite: boolean): void {
.option(`S`, {
alias: `https`,
type: `boolean`,
describe: `Use HTTPS. See https://www.gatsbyjs.org/docs/local-https/ as a guide`,
describe: `Use HTTPS. See https://www.gatsbyjs.com/docs/local-https/ as a guide`,
})
.option(`c`, {
alias: `cert-file`,
type: `string`,
default: ``,
describe: `Custom HTTPS cert file (also required: --https, --key-file). See https://www.gatsbyjs.org/docs/local-https/`,
describe: `Custom HTTPS cert file (also required: --https, --key-file). See https://www.gatsbyjs.com/docs/local-https/`,
})
.option(`k`, {
alias: `key-file`,
type: `string`,
default: ``,
describe: `Custom HTTPS key file (also required: --https, --cert-file). See https://www.gatsbyjs.org/docs/local-https/`,
describe: `Custom HTTPS key file (also required: --https, --cert-file). See https://www.gatsbyjs.com/docs/local-https/`,
})
.option(`ca-file`, {
type: `string`,
default: ``,
describe: `Custom HTTPS CA certificate file (also required: --https, --cert-file, --key-file). See https://www.gatsbyjs.org/docs/local-https/`,
describe: `Custom HTTPS CA certificate file (also required: --https, --cert-file, --key-file). See https://www.gatsbyjs.com/docs/local-https/`,
})
.option(`graphql-tracing`, {
type: `boolean`,
Expand All @@ -174,11 +181,11 @@ function buildLocalCommands(cli: yargs.Argv, isLocalSite: boolean): void {
})
.option(`inspect`, {
type: `number`,
describe: `Opens a port for debugging. See https://www.gatsbyjs.org/docs/debugging-the-build-process/`,
describe: `Opens a port for debugging. See https://www.gatsbyjs.com/docs/debugging-the-build-process/`,
})
.option(`inspect-brk`, {
type: `number`,
describe: `Opens a port for debugging. Will block until debugger is attached. See https://www.gatsbyjs.org/docs/debugging-the-build-process/`,
describe: `Opens a port for debugging. Will block until debugger is attached. See https://www.gatsbyjs.com/docs/debugging-the-build-process/`,
}),
handler: handlerP(
getCommandHandler(`develop`, (args: yargs.Arguments, cmd: Function) => {
Expand Down Expand Up @@ -347,7 +354,7 @@ function buildLocalCommands(cli: yargs.Argv, isLocalSite: boolean): void {

cli.command({
command: `repl`,
describe: `Get a node repl with context of Gatsby environment, see (https://www.gatsbyjs.org/docs/gatsby-repl/)`,
describe: `Get a node repl with context of Gatsby environment, see (https://www.gatsbyjs.com/docs/gatsby-repl/)`,
handler: getCommandHandler(
`repl`,
(args: yargs.Arguments, cmd: Function) => {
Expand Down Expand Up @@ -481,39 +488,6 @@ export const createCli = (argv: Array<string>): yargs.Arguments => {
await initStarter(starterStr, rootPathStr)
}),
})
.command(`plugin`, `Useful commands relating to Gatsby plugins`, yargs =>
yargs
.command({
command: `docs`,
describe: `Helpful info about using and creating plugins`,
handler: handlerP(() =>
console.log(`
Using a plugin:
- What is a Plugin? (https://www.gatsbyjs.org/docs/what-is-a-plugin/)
- Using a Plugin in Your Site (https://www.gatsbyjs.org/docs/using-a-plugin-in-your-site/)
- What You Don't Need Plugins For (https://www.gatsbyjs.org/docs/what-you-dont-need-plugins-for/)
- Loading Plugins from Your Local Plugins Folder (https://www.gatsbyjs.org/docs/loading-plugins-from-your-local-plugins-folder/)
- Plugin Library (https://www.gatsbyjs.org/plugins/)
Creating a plugin:
- Naming a Plugin (https://www.gatsbyjs.org/docs/naming-a-plugin/)
- Files Gatsby Looks for in a Plugin (https://www.gatsbyjs.org/docs/files-gatsby-looks-for-in-a-plugin/)
- Creating a Generic Plugin (https://www.gatsbyjs.org/docs/creating-a-generic-plugin/)
- Creating a Local Plugin (https://www.gatsbyjs.org/docs/creating-a-local-plugin/)
- Creating a Source Plugin (https://www.gatsbyjs.org/docs/creating-a-source-plugin/)
- Creating a Transformer Plugin (https://www.gatsbyjs.org/docs/creating-a-transformer-plugin/)
- Submit to Plugin Library (https://www.gatsbyjs.org/contributing/submit-to-plugin-library/)
- Source Plugin Tutorial (https://www.gatsbyjs.org/tutorial/source-plugin-tutorial/)
- Maintaining a Plugin (https://www.gatsbyjs.org/docs/maintaining-a-plugin/)
- Join Discord #plugin-authoring channel to ask questions! (https://gatsby.dev/discord/)
`)
),
})
.demandCommand(
1,
`Pass --help to see all available commands and options.`
)
)
.command({
command: `telemetry`,
describe: `Enable or disable Gatsby anonymous analytics collection.`,
Expand All @@ -534,6 +508,95 @@ Creating a plugin:
report.log(`Telemetry collection ${enabled ? `enabled` : `disabled`}`)
}),
})
.command({
command: `plugin [cmd]`,
describe: `Useful commands relating to Gatsby plugins`,
builder: yargs =>
yargs.positional(`cmd`, {
choices: [`docs`],
describe: "Valid commands include `docs`.",
type: `string`,
}),
handler: handlerP(({ cmd }) => {
if (cmd === `docs`) {
console.log(`
Using a plugin:
- What is a Plugin? (https://www.gatsbyjs.com/docs/what-is-a-plugin/)
- Using a Plugin in Your Site (https://www.gatsbyjs.com/docs/using-a-plugin-in-your-site/)
- What You Don't Need Plugins For (https://www.gatsbyjs.com/docs/what-you-dont-need-plugins-for/)
- Loading Plugins from Your Local Plugins Folder (https://www.gatsbyjs.com/docs/loading-plugins-from-your-local-plugins-folder/)
- Plugin Library (https://www.gatsbyjs.com/plugins/)
Creating a plugin:
- Naming a Plugin (https://www.gatsbyjs.com/docs/naming-a-plugin/)
- Files Gatsby Looks for in a Plugin (https://www.gatsbyjs.com/docs/files-gatsby-looks-for-in-a-plugin/)
- Creating a Generic Plugin (https://www.gatsbyjs.com/docs/creating-a-generic-plugin/)
- Creating a Local Plugin (https://www.gatsbyjs.com/docs/creating-a-local-plugin/)
- Creating a Source Plugin (https://www.gatsbyjs.com/docs/creating-a-source-plugin/)
- Creating a Transformer Plugin (https://www.gatsbyjs.com/docs/creating-a-transformer-plugin/)
- Submit to Plugin Library (https://www.gatsbyjs.com/contributing/submit-to-plugin-library/)
- Source Plugin Tutorial (https://www.gatsbyjs.com/tutorial/source-plugin-tutorial/)
- Maintaining a Plugin (https://www.gatsbyjs.com/docs/maintaining-a-plugin/)
- Join Discord #plugin-authoring channel to ask questions! (https://gatsby.dev/discord/)
`)
} else {
console.log(`Current valid subcommands are: 'docs'`) // right now this is hardcoded because we only have a single command
}
}),
})
.command({
command: `options [cmd] [key] [value]`,
describe: `View or set your gatsby-cli configuration settings.`,
builder: yargs =>
yargs
.positional(`cmd`, {
choices: [`set`],
type: `string`,
describe: `Configure your package manager.`,
})
.positional(`key`, {
choices: [`pm`, `package-manager`],
type: `string`,
describe: `Set the package manager \`gatsby new\` is using.`,
})
.positional(`value`, {
choices: [`npm`, `yarn`],
type: `string`,
describe: `Set package manager as \`npm\` or \`yarn\`.`,
}),

handler: handlerP(({ cmd, key, value }: yargs.Arguments) => {
if (!getPackageManager()) {
setPackageManager(`npm`)
}

if (cmd === `set`) {
if (key === `pm` || key === `package-manager`) {
if (value && value !== `yarn` && value !== `npm`) {
report.panic(`Package manager must be yarn or npm.`)
}

if (value) {
// @ts-ignore
setPackageManager(value)
return
} else {
setPackageManager(`npm`)
}
} else {
reporter.warn(
`Please pass your desired config key and value. Currently you can only set your package manager using \`pm\`.`
)
}
return
}

console.log(`
Package Manager: ${getPackageManager()}
Telemetry enabled: ${isTrackingEnabled()}
`)
}),
})
.wrap(cli.terminalWidth())
.demandCommand(1, `Pass --help to see all available commands and options.`)
.strict()
Expand Down
34 changes: 14 additions & 20 deletions packages/gatsby-cli/src/init-starter.ts
Expand Up @@ -11,8 +11,7 @@ import prompts from "prompts"
import url from "url"
import { updateSiteMetadata } from "gatsby-core-utils"
import report from "./reporter"
import { getPackageManager, promptPackageManager } from "./util/package-manager"
import { isTTY } from "./util/is-tty"
import { getPackageManager, setPackageManager } from "./util/package-manager"
import reporter from "../lib/reporter"

const spawnWithArgs = (
Expand All @@ -29,26 +28,13 @@ const spawn = (
const [file, ...args] = cmd.split(/\s+/)
return spawnWithArgs(file, args, options)
}
// Checks the existence of yarn package and user preference if it exists
// 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
const shouldUseYarn = async (): Promise<boolean> => {
const checkForYarn = async (): Promise<boolean> => {
try {
execSync(`yarnpkg --version`, { stdio: `ignore` })

let packageManager = getPackageManager()
if (!packageManager) {
// if package manager is not set:
// - prompt user to pick package manager if in interactive console
// - default to yarn if not in interactive console
if (isTTY()) {
packageManager = (await promptPackageManager()) || `yarn`
} else {
packageManager = `yarn`
}
}

return packageManager === `yarn`
return true
} catch (e) {
return false
}
Expand Down Expand Up @@ -115,8 +101,16 @@ const install = async (rootPath: string): Promise<void> => {
process.chdir(rootPath)

try {
if (await shouldUseYarn()) {
await fs.remove(`package-lock.json`)
if (!getPackageManager()) {
setPackageManager(`npm`)
}
if (getPackageManager() === `yarn` && checkForYarn()) {
if (await fs.pathExists(`package-lock.json`)) {
if (!(await fs.pathExists(`yarn.lock`))) {
await spawn(`yarnpkg import`)
}
await fs.remove(`package-lock.json`)
}
await spawn(`yarnpkg`)
} else {
await fs.remove(`yarn.lock`)
Expand Down
23 changes: 0 additions & 23 deletions packages/gatsby-cli/src/util/package-manager.ts
@@ -1,5 +1,4 @@
import { getConfigStore } from "gatsby-core-utils"
import prompts from "prompts"
import report from "../reporter"

type PackageManager = "yarn" | "npm"
Expand All @@ -11,25 +10,3 @@ export const setPackageManager = (packageManager: PackageManager): void => {
getConfigStore().set(packageMangerConfigKey, packageManager)
report.info(`Preferred package manager set to "${packageManager}"`)
}

export const promptPackageManager = async (): Promise<PackageManager> => {
const promptsAnswer: {
package_manager: PackageManager
} = await prompts([
{
type: `select`,
name: `package_manager`,
message: `Which package manager would you like to use ?`,
choices: [
{ title: `yarn`, value: `yarn` },
{ title: `npm`, value: `npm` },
],
initial: 0,
},
])
const response = promptsAnswer.package_manager
if (response) {
setPackageManager(response)
}
return response
}
4 changes: 2 additions & 2 deletions scripts/publish-starters.sh
Expand Up @@ -27,8 +27,8 @@ for folder in $GLOB; do
cp -r "$BASE/$folder/." .

if [ "$IS_WORKSPACE" = null ]; then
rm -rf yarn.lock
yarn import # generate a new yarn.lock file based on package-lock.json
rm -f yarn.lock
yarn import # generate a new yarn.lock file based on package-lock.json, gatsby new does this is new CLI versions but will ignore if file exists
fi

if [ -n "$(git status --porcelain)" ]; then
Expand Down

0 comments on commit 5658b87

Please sign in to comment.