ignite icon indicating copy to clipboard operation
ignite copied to clipboard

New Ignite walkthrough

Open jamonholmgren opened this issue 1 year ago • 0 comments

I’ve been rethinking the whole “Ignite CLI runs without asking any questions” thing we have going on. There are some benefits to it, but there’s also some benefit of asking the questions in a walkthrough where it can feel exciting / inspire more confidence.

$ npx ignite-cli new

🔥 About to Ignite your new app! 🔥

 ↣ What do you want to call it? PizzaApp
 ↣ What bundle identifier? com.infinitered.pizzaapp
 ↣ Want to use Expo? Y/n
 ↣ Want us to install dependencies for you? (adds 50-100 seconds) Y/n

In the future, if you'd like to skip the questions, you can run Ignite with these options:

  npx ignite-cli new PizzaApp --bundle=com.infinitered.pizzaapp --expo --install-deps

<Ignite continues>

Note that we give them the command for skipping the questions next time, if they want.

Primarily, this surfaces the Expo and bundle identifier options, which are somewhat hidden otherwise.

I think this makes sense to include in Maverick.

jamonholmgren avatar Jul 22 '22 16:07 jamonholmgren

I was thinking of running a similar behavior of npm init, where you have a few options:

  • By default, all npm init will prompt you to go through all the options, with yes or no, and give a text field if the option requires input
  • If you pass in npm init -y, you are saying "yes" to all the question prompts

For npx ignite-cli new, we should have the following behavior

Command Question Prompts? Description
npx ignite-cli new Yes Go through each option as a question prompt, with a command outputted with flags for selected options. Example: npx ignite-cli new PizzaApp --bundle=com.infinitered.pizzaapp --expo --install-deps
npx ignite-cli new PizzaApp Yes Go through each option as a question prompt, with a command outputted with flags for selected options. Example: npx ignite-cli new PizzaApp --bundle=com.infinitered.pizzaapp --expo --install-deps. Since name being the first parameter is already the existing behavior, I think still prompting a question is important since most users will go through this flow.
npx ignite-cli new PizzaApp --bundle=com.infinitered.pizzaapp --expo --install-deps No Go straight to initializing
npx ignite-cli new PizzaApp --install-deps No If only partial options are passed, assume existing defaults for not included flag options
npx ignite-cli new PizzaApp --y No Current CLI behavior, use all default options and skip straight to initializing

joshuayoes avatar Aug 10 '22 22:08 joshuayoes

Nice write up, I like this idea!

Also for clarity if you want to edit the Issue and your comment:

  • --expo flag gets removed once I merge my unification PR (happening shortly)
  • --overwrite is a flag to make note of here

frankcalise avatar Aug 10 '22 23:08 frankcalise

Thanks @joshuayoes! Good write-up.

I'm thinking over the "If only partial options are passed, assume existing defaults for not included flag options". My initial reaction is that's not super intuitive to me. I do like the -y option though, to assume defaults for the others.

What do the rest of you think?

jamonholmgren avatar Aug 10 '22 23:08 jamonholmgren

export interface Options {
  /**
   * Log raw parameters for debugging, run formatting script not quietly
   * @default false
   */
  debug?: boolean
  /**
   * Remove existing directory otherwise throw if exists
   * @default false
   */
  overwrite?: boolean
  /**
   * @deprecated flag left in for backwards compatability, warn them to use old Ignite
   * @default undefined
   */
  boilerplate?: string
  /**
   * alias for `boilerplate`
   * @deprecated flag left in for backwards compatability, warn them to use old Ignite
   * @default undefined
   */
  b?: string
  /**
   * custom bundle identifier (android only)
   * @default `com.${name}`
   * @example 'com.pizzaapp'
   */
  bundle?: string
  /**
   * @deprecated this option is deprecated. Ignite sets you up to run native or Expo
   * @default undefined
   */
  expo?: boolean
  /**
   * Package manager to install dependencies with
   *
   * Preference order: `pnpm`, `yarn`, `npm`
   */
  packager?: "npm" | "yarn" | "pnpm"
  /**
   * Create new git repository and create an inital commit with boilerplate changes
   * @default true
   */
  git?: boolean
  /**
   * React Native Colo Loco is no longer installed with Ignite,
   * but we will give instructions on how to install it if they pass in `--colo-loco`   *
   * @default false
   */
  coloLoco?: boolean
}

These are the options as they exist on maverick currently

joshuayoes avatar Aug 10 '22 23:08 joshuayoes

These are the options that I am planning on implementing. All options will be available in parameters.options passed via a flag in the command like --install-deps, but the debug and deprecated options will not be prompted for in the questions prompt workflow

export interface Options {
  /**
   * Log raw parameters for debugging, run formatting script not quietly
   *
   * Input Source: `prompt.confirm` | `parameter.option`
   * @default false
   */
  debug?: boolean
  /**
   * Remove existing directory otherwise throw if exists
   *
   * Input Source: `prompt.confirm` | `parameter.option`
   * @default false
   */
  overwrite?: boolean
  /**
   * Input Source: `parameter.option`
   * @deprecated flag left in for backwards compatability, warn them to use old Ignite
   * @default undefined
   */
  boilerplate?: string
  /**
   * alias for `boilerplate`
   *
   * Input Source: `parameter.option`
   * @deprecated flag left in for backwards compatability, warn them to use old Ignite
   * @default undefined
   */
  b?: string
  /**
   * custom bundle identifier for iOS and Android bundle
   *
   * Input Source: `prompt.ask` | `parameter.option`
   * @default `com.${name}`
   * @example 'com.pizzaapp'
   */
  bundle?: string
  /**
   * Input Source: `parameter.option`
   * @deprecated this option is deprecated. Ignite sets you up to run native or Expo
   * @default undefined
   */
  expo?: boolean
  /**
   * Package manager to install dependencies with
   *
   * Input Source: `prompt.ask`| `parameter.option`
   *
   * Default: packager that executed current command, i.e. `npx ignite new`, `yarn dlx ignite new`, `pnpm dlx ignite new`
   */
  packager?: "npm" | "yarn" | "pnpm"
  /**
   * Create new git repository and create an inital commit with boilerplate changes
   *
   * Input Source: `prompt.confirm` | `parameter.option`
   * @default true
   */
  git?: boolean
  /**
   * Whether or not to run packager install script after project is created
   *
   * @default true
   */
  installDeps?: boolean
  /**
   * React Native Colo Loco is no longer installed with Ignite,
   * but we will give instructions on how to install it if they pass in `--colo-loco`   *
   *
   * Input Source: `prompt.confirm` | `parameter.option`
   * @default false
   */
  coloLoco?: boolean
}

joshuayoes avatar Aug 11 '22 00:08 joshuayoes

One note: bundle is used on iOS and Android, despite the note. (This is why comments are a two-edged sword....)

jamonholmgren avatar Aug 11 '22 00:08 jamonholmgren

I'm thinking over the "If only partial options are passed, assume existing defaults for not included flag options". My initial reaction is that's not super intuitive to me

I spent last night thinking about it, and I feel like there are two types of consumers of any CLI:

  • a user who is at the keyboard
  • a scripting environment like a cloud CI server or a bash script

In the user case, it's okay the prompt the interactive prompt, because they can hit the keys to walk through it.

But if it is a CI / bash consumer, an interactive prompt will break the functionality. I feel like if someone provides any flag, generally it is someone who is iterating on a specific command. But I could see a situation where someone is writing a bash script, but they forget to provide a flag, and their script is broken by the interactive prompt getting activated because they forgot one option.

That's my thought on it. There are also a few other options to consider:

  • add a flag to explicitly disable a question prompt, and prompt missing flags by default
  • throw an error if some flags are provided, but others aren't

joshuayoes avatar Aug 11 '22 17:08 joshuayoes

One note: bundle is used on iOS and Android, despite the note. (This is why comments are a two-edged sword....)

That is a good catch! I'll update that comment

joshuayoes avatar Aug 11 '22 17:08 joshuayoes

Here is a sample of what I imagined for the question prompts

$ npx ignite-cli new

🔥 About to Ignite your new app! 🔥

 ↣ What do you want to call it? PizzaApp
 ↣ What bundle identifier? com.infinitered.pizzaapp
 ↣ Where do you want to start your project? ~/Current_Directory/PizzaApp
 ↣ Do you want to overwrite the folder at the target directory (if it exists)? y/N 
 ↣ Create a new git repository and create an initial commit? Y/n
 ↣ What package manager do you want to use? npm
 ↣ Want us to install dependencies for you? (adds 50-100 seconds) Y/n

In the future, if you'd like to skip the questions, you can run Ignite with these options:

  npx ignite-cli new PizzaApp --bundle=com.infinitered.pizzaapp --target=~/Current_Directory/PizzaApp --overwrite=false --git --packager=npm --install-deps

<Ignite continues>

joshuayoes avatar Aug 11 '22 17:08 joshuayoes

I think @joshuayoes that I'd just say "For CI, use -y to bypass any non-provided options and use defaults." The more I think about it, the less I like the behavior of skipping options if any are provided.

With the list you did, I like it, but I'd remove the "where do you want to start your project" and only prompt the overwrite if the folder exists (it's not necessary to even show it if the folder doesn't).

The rest looks really good. The package manager should default to whatever we would use normally.

jamonholmgren avatar Aug 11 '22 18:08 jamonholmgren

Currently, our package manager behavior is to prefer the following order:

  • Vanilla: pnpm -> yarn -> npm
  • Expo: yarn -> npm

Previously, we didn't let people use pnpm use expo, but it looks like that Expo now supports it?

Expo in their docs seems to prefer yarn as their recommended package manager.

So perhaps we should do: yarn -> pnpm -> npm? Now that we have unified expo and vanilla project starts


Edit: since the prompt.ask can do a list, I'm going to choose yarn as the default, since that's what the docs recommend, and then allow npm and pnpm as options

joshuayoes avatar Aug 11 '22 19:08 joshuayoes

Here is an updated table of the behavior I'm planning on implementing based on @jamonholmgren's feedback

Command Question Prompts? Description
npx ignite-cli new Yes Go through each option as a question prompt, with a command outputted with flags for selected options. Example: npx ignite-cli new PizzaApp --bundle=com.infinitered.pizzaapp --target=~/Current_Directory/PizzaApp --overwrite=false --git --packager=npm --install-deps
npx ignite-cli new PizzaApp Yes Go through each option as a question prompt, with a command outputted with flags for selected options. Example: npx ignite-cli new PizzaApp --bundle=com.infinitered.pizzaapp --target=~/Current_Directory/PizzaApp --overwrite=false --git --packager=npm --install-deps. Since name being the first parameter is already the existing behavior, I think still prompting a question is important since most users will go through this flow.
npx ignite-cli new PizzaApp --install-deps Yes If only partial options are passed, prompt for not included options
npx ignite-cli new PizzaApp --bundle=com.infinitered.pizzaapp --target=~/Current_Directory/PizzaApp --overwrite=false --git --packager=npm --install-deps No All options passed, go straight to initializing
npx ignite-cli new PizzaApp --y No Current CLI behavior, use all default options and skip straight to initializing
npx ignite-cli new PizzaApp --y --install-deps No If only partial options are passed, assume existing defaults for not included flag options

joshuayoes avatar Aug 11 '22 19:08 joshuayoes

Should we be dropping the yarn.lock file from the boilerplate since essentially npx ignite-cli new copies the boilerplate directory into the named project directory and then runs [packager of choice] install?

If using npm, it'll create it's package-lock.json, etc

frankcalise avatar Aug 12 '22 03:08 frankcalise

I think for now, I would prefer to remove adding a lock file because that would introduce a lot more maintenance overhead (adding one for yarn, npm, and pnpm every time we make a change).

However, adding a lock file would also make boilerplates more stable because we'd have the dependencies pinned.

I'm going to remove the lock file from the boilerplate, and then we can add the extra complexity of managing 3 lock files if we start getting issues related to dependencies.

joshuayoes avatar Aug 12 '22 19:08 joshuayoes

Resolved by https://github.com/infinitered/ignite/pull/1999

joshuayoes avatar Aug 22 '22 16:08 joshuayoes