We use [rush](https://rushjs.io/) with [pnpm](https://pnpm.js.org) to manage our monorepo. All your commands to build and test will use `rush`/`rushx`.
- DO NOT USE `npm install` (and in general avoid `npm` commands). If you need to add a package, look at `rush add` or modify the package.json directly.
- We don't hoist common dev dependencies from a single list. It must be declared in each package, but pnpm will only install it once.
- You can use `rush --help` to get more details about what commands you can run.
- You can also use `rushx` to run specific commands in a given package (but rush install/link usually needs to have run for it to work).
- CREATE - standard command to create a new resource. Usually backed server-side by a PUT request.
- UPDATE - command to selectively update properties of a resource and preserve existing values. May be backed server-side by either a PUT or PATCH request.
- SET - command to replace all properties of a resource without preserving existing values, typically backed server-side by a PUT request.
- SHOW - command to show the properties of a resource, backed server-side by a GET request.
- LIST - command to list instances of a resource, backed server-side by a GET request.
- DELETE - command to delete a resource, backed server-side by a DELETE request.
- WAIT - command that polls a GET endpoint until a condition is reached.
* In general, DO NOT put units in Flag names. ALWAYS put the expected units in the help text. Example: --durationinminutes should simply be --duration. This prevents the need to add more arguments later if more units are supported.
* Consider allowing a syntax that will let the user specify units. For example, even if the service requires a value in minutes, consider accepting 1h or 60m. It is fine to assume a default (i.e. 60 = 60 minutes).
* It is acceptable to use a unit in the flag name when it is used like an enum. For example, --startday is okay when it accepts MON, TUE, etc. --starthour is okay when it indicates an hour of the day.
* Avoid having multiple arguments that simply represent different ways of getting the same thing. Instead, use a single descriptive name and overload it appropriately. For example, assume a command which can accept a parameter file through a URL or local path.
### Porting Rules
* Always cleanup, remove redundant, or legacy items.
* Always prefer global form and provided functionality.
* Always use global configuration - Do not port configuration files, move settings to global config.
* Correctness is higher priority then velocity (e.g. remove QnAMaker --legacy, chatdown --stdin, abstract out libraries, clean up messages - this is *not* 1-1 porting, it's more of 1 --> 1+cleanup+improve porting)
### Usage and Readme Rules
* Always decorate option as:
* Optional: Option is not required
* Mandatory: Option is required
* Default=\<val\> : If option has a default value, it must be displayed
* Command and option descriptions shall be short, precise and leverage industry common notions
* All ReadMe's shall follow the same structure as the primary cli package (also use chatdown or ludown as examples)
* Ensure all usage contains the standard format:
SYNOPSIS: what does it do
VERSION: git version
USAGE: command form
OPTIONS: Available options at this command group level
COMMANDS: Available sub-commands
EXAMPLES: Representative usage examples
* **Important**: Pay special attention to descriptions, command & option names. That's your user primary discovery & understanding way to know what it does.
## Software Development Lifecycle Requirement
CLI contribution Software Development Lifecycle is as follows:
1. Spec it out.
1. If new, provide a full spec per templates provided in this folder.
2. If porting, specify changes from original implementation
3. Ensure to conform to the above command line specification rules
2. Get spec reviewed & approved. Ensure sign off by gate-keeper (as will be triaged weekly).
3. Implement. All code must be test-covered at > 90% coverage integrated into CI.
4. Schedule a team show & tell demo for introduction, feedback and fine tuning
Rush and pnpm are newer tools and not all that popular outside of Microsoft, why use them?
- Speed. We get ordered and parallel builds for free.
- Standarization. Many of the Microsoft JS repos are moving to `rush`.
- Quality of life. The command line help, enforcement & customization tools, etc. that come from `rush` and `pnpm` are super useful. Also, we like avoiding the "parent" project for hoisting dependencies. That frequently bites us with our old system.
### Steps to create a new plugin
1. Build the project
2. Inside the packages folder(https://github.com/microsoft/botframework-cli/tree/master/packages) run 'npx oclif plugin <plugin-name>'
3. Follow the wizard and set the prompts:
? npm package: @microsoft/bf-<plugin-name>
? description: <Pluginbriefdescription>
? author: Microsoft
? version: 1.0.0
? license: MIT
? Who is the GitHub owner of repository (https://github.com/OWNER/repo): microsoft
? What is the GitHub name of repository (https://github.com/owner/REPO): botframework-cli
? Select a package manager: npm
? TypeScript: Y
? Use tslint (linter for TypeScript): Y
? Use mocha (testing framework): Y
? Add CI service config (Press <space> to select, <a> to toggle all, <i> to invert selection): select any
4. Go to the folder created by the previous command and add @microsoft/bf-cli-command as a dependency in your package.json file
5. Run "rush update" and "rush build" from root or package root
6. To run the new command locally, run "bin\run <command-name>" from the package root, ie \botframework-cli\packages\<package-name>\bin\run <command-name>