diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 02c8139d..ce70847c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,10 +2,12 @@ balenaCLI is an open source project and your contribution is welcome! -* Install the dependencies listed in the [NPM Installation](./INSTALL.md#npm-installation) - section of the `INSTALL.md` file. Check the section [Additional - Dependencies](./INSTALL.md#additional-dependencies) too. -* Clone the `balena-cli` repository, `cd` to it and run `npm install`. +* Install the dependencies listed in the [NPM Installation + section](./INSTALL-ADVANCED.md#npm-installation) section of the installation instructions. Check + the section [Additional Dependencies](./INSTALL-ADVANCED.md#additional-dependencies) too. +* Clone the `balena-cli` repository (or a [forked + repo](https://docs.github.com/en/free-pro-team@latest/github/getting-started-with-github/fork-a-repo), + if you are not in the balena team), `cd` to it and run `npm install`. * Build the CLI with `npm run build` or `npm test`, and execute it with `./bin/balena` (on a Windows command prompt, you may need to run `node .\bin\balena`). @@ -21,8 +23,8 @@ this will only help if you add some test cases for your new code! ## ./bin/balena-dev and oclif -When using `./bin/balena-dev` with oclif-converted commands, it is currently necessary to manually -edit the `oclif` section of `package.json` to replace `./build` with `./lib` as follows: +When using `./bin/balena-dev`, it is currently necessary to manually edit the `oclif` section of +`package.json` to replace `./build` with `./lib` as follows: Change from: ``` @@ -44,7 +46,7 @@ And then remember to change it back before pushing the pull request. This is obv and inconvenient, and improvement suggestions are welcome: is there a better solution than automatically editing `package.json`? It is doable, if it is what needs to be done. -## Semantic versioning and commit messages +## Semantic versioning, commit messages and the ChangeLog The CLI version numbering adheres to [Semantic Versioning](http://semver.org/). The following header/row is required in the body of a commit message, and will cause the CI build to fail if absent: @@ -56,7 +58,29 @@ Change-type: patch|minor|major Version numbers and commit messages are automatically added to the `CHANGELOG.md` file by the CI build flow, after a pull request is merged. It should not be manually edited. -## Editing documentation files (CHANGELOG, README, website...) +If `package.json` is updated for dependencies listed in the `repo.yml` file (like `balena-sdk`), +the commit message body should include a line in the following format: +``` +Update balena-sdk from 12.0.0 to 12.1.0 +``` + +This allows the CI to produce nested change logs (with expandable arrows), pulling in commit +messages from the upstream repositories. The following npm script can be used to automatically +produce a commit with a suitable commit message: +``` +npm run update balena-sdk ^12.1.0 +``` + +The script will create a new branch (only if `master` is currently checked out), run `npm update` +with the given target version and commit the `package.json` and `npm-shrinkwrap.json` files. The +script by default will set the `Change-type` to `patch` or `minor`, depending on the semver change +of the updated dependency. For a `major` change type, it can specified as an extra argument: +``` +npm run update balena-sdk ^12.14.0 patch +npm run update balena-sdk ^13.0.0 major +``` + +## Editing documentation files (README, INSTALL, Reference website...) The `doc/cli.markdown` file is automatically generated by running `npm run build:doc` (which also runs as part of `npm run build`). That file is then pulled by scripts in the @@ -65,72 +89,70 @@ Documentation page](https://www.balena.io/docs/reference/cli/). The content sources for the auto generation of `doc/cli.markdown` are: -* Selected sections of the README file. -* The CLI's command documentation in source code (both Capitano and oclif commands), for example: - * `lib/actions/build.coffee` +* [Selected + sections](https://github.com/balena-io/balena-cli/blob/v12.23.0/automation/capitanodoc/capitanodoc.ts#L199-L204) + of the README file. +* The CLI's command documentation in source code (`/lib/actions-oclif/` folder), for example: + * `lib/actions-oclif/push.ts` * `lib/actions-oclif/env/add.ts` The README file is manually edited, but subsections are automatically extracted for inclusion in `doc/cli.markdown` by the `getCapitanoDoc()` function in [`automation/capitanodoc/capitanodoc.ts`](https://github.com/balena-io/balena-cli/blob/master/automation/capitanodoc/capitanodoc.ts). -The `INSTALL.md` and `TROUBLESHOOTING.md` files are also manually edited. +The `INSTALL*.md` and `TROUBLESHOOTING.md` files are also manually edited. ## Windows -Please note that `npm run build:installer` (which generates the `.exe` executable installer on -Windows) specifically requires [MSYS2](https://www.msys2.org/) to be installed. Other than that, -the standard Command Prompt or PowerShell can be used (though MSYS2 is still handy, as it provides -'git' and a number of common unix utilities). If you make changes to `package.json` scripts, check -they also run on a standard Windows Command Prompt. +The `npm run build:installer` script (which generates the `.exe` executable installer on Windows) +specifically requires [MSYS2](https://www.msys2.org/) to be installed. Other than that, the +standard Command Prompt or PowerShell can be used (though MSYS2 is still handy, as it provides +'git' and a number of common unix utilities). If changes are made to npm scripts in `package.json`, +check that they also run on a standard Windows Command Prompt. ## Updating the 'npm-shrinkwrap.json' file The `npm-shrinkwrap.json` file is used to control package dependencies, as documented at https://docs.npmjs.com/files/shrinkwrap.json. -While developing, the `package.json` file is often modified by, or before, running `npm install` -in order to add, remove or modify dependencies. When `npm install` is executed, it automatically -updates the `npm-shrinkwrap.json` file as well, **taking into account not only the `package.json` -file but also the current state of the `node_modules` folder in your computer.** +Changes to `npm-shrinkwrap.json` can be automatically merged by git during operations like +`rebase`, `pull` and `cherry-pick`, but in some cases this results in suboptimal dependency +resolution (the `node_modules` folder may end up larger than necessary, with consequences to CLI +load time too). For this reason, the recommended way to update `npm-shrinkwrap.json` is to run +`npm install`, possibly alongside `npm dedupe` as well. The following commands can be used to +fix shrinkwrap issues and optimize the dependencies: -Meanwhile, as a text (JSON) file, `git` is capable of merging the `npm-shrinkwrap.json` file during -operations like `rebase`, `cherry-pick` and `pull`. But git's automated merge is not the -recommended way of updating the `npm-shrinkwrap.json` file, because it does not take into account -duplicates or conflicts in the dependency tree, or indeed the state of the `package.json` file -(which may have just been merged). You can improve this by installing the npm merge driver with: +```sh +git checkout master -- npm-shrinkwrap.json +rm -rf node_modules +npm install # update npm-shrinkwrap.json to satisfy changes to package.json +npm dedupe # deduplicate dependencies from npm-shrinkwrap.json +npm install # re-add optional dependencies removed by dedupe +git add npm-shrinkwrap.json # add it for committing (solve merge errors) ``` + +Note that `npm dedupe` should always be followed by `npm install`, as shown above, even if +`npm install` had already been executed before `npm dedupe`. + +Optionally, these steps may be automated by installing the +[npm-merge-driver](https://www.npmjs.com/package/npm-merge-driver): + +```sh npx npm-merge-driver install -g ``` -Whether or not there is a merge error, the following commands are the recommended way of updating -and committing the `npm-shrinkwrap.json` file: - -```bash -$ npm install # fetch the latest modules update the npm-shrinkwrap.json file -$ npm dedupe # deduplicate dependencies from the npm-shrinkwrap.json file -$ npm install # re-add optional dependencies for other platforms that may have been removed by dedupe -$ git add npm-shrinkwrap.json # add it for committing (solve merge errors) -``` - ## TypeScript and oclif The CLI currently contains a mix of plain JavaScript and [TypeScript](https://www.typescriptlang.org/) code. The goal is to have all code written in Typescript, in order to take advantage of static typing and formal programming interfaces. The migration towards Typescript is taking place gradually, as part of maintenance work or -the implementation of new features. Historically, the CLI was originally written in -[CoffeeScript](https://coffeescript.org), but all CoffeeScript code was migrated to either -Javascript or Typescript. +the implementation of new features. -Similarly, [Capitano](https://github.com/balena-io/capitano) was originally adopted as the CLI's -framework, but later we decided to take advantage of [oclif](https://oclif.io/)'s features such -as native installers for Windows, macOS and Linux, and support for custom flag parsing (for -example, we're still battling with Capitano's behavior of dropping leading zeros of arguments that -look like integers, such as some abbreviated UUIDs). Again, the migration is taking place -gradually, with some CLI commands parsed by oclif and others by Capitano. A simple command line -pre-parsing takes place in `preparser.ts`, to decide whether to route full parsing to Capitano or -to oclif. +Of historical interest, the CLI was originally written in [CoffeeScript](https://coffeescript.org) +and used the [Capitano](https://github.com/balena-io/capitano) framework. All CoffeeScript code was +migrated to either Javascript or Typescript, and Capitano was replaced with oclif. A few file or +variable names still refer to this legacy, for example `automation/capitanodoc/capitanodoc.ts`. ## Programming style @@ -138,29 +160,6 @@ to oclif. reformats the code. Beyond that, we have a preference for Javascript promises over callbacks, and for `async/await` over `.then()`. -## Updating upstream dependencies - -In order to get proper nested changelogs, when updating upstream modules that are in the repo.yml -(like the balena-sdk), the commit body has to contain a line with the following format: -``` -Update balena-sdk from 12.0.0 to 12.1.0 -``` - -Since this is error prone, it's suggested to use the following npm script: -``` -npm run update balena-sdk ^12.1.0 -``` - -This will create a new branch (only if you are currently on master), run `npm update` with the -version you provided as a target and commit the package.json & npm-shrinkwrap.json. The script by -default will set the `Change-type` to `patch` or `minor`, depending on the semver change of the -updated dependency, but if you need to use a different one (eg `major`) you can specify it as an -extra argument: -``` -npm run update balena-sdk ^12.14.0 patch -npm run update balena-sdk ^13.0.0 major -``` - ## Common gotchas One thing that most CLI bugs have in common is the absence of test cases exercising the broken