build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
/* global __dirname process require */
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
|
|
|
|
|
const chalk = require('chalk');
|
|
|
|
|
const {execSync} = require('child_process');
|
|
|
|
|
const minimist = require('minimist');
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
const path = require('path');
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
const {readJsonSync} = require('fs-extra');
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
|
|
|
|
|
const args = minimist(process.argv.slice(2));
|
|
|
|
|
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
const DEFAULT_BUMP = null;
|
|
|
|
|
const bump = args._[0] || DEFAULT_BUMP;
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
const DEFAULT_COMMIT_MSG = `chore(release): %v`;
|
|
|
|
|
const commitMsg = args['commit-message'] || DEFAULT_COMMIT_MSG;
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
const DEFAULT_CONVENTIONAL_COMMITS = true;
|
|
|
|
|
let cCommits;
|
|
|
|
|
// with --no-conventional-commits cli option `args['conventional-commits']` will be `false`
|
|
|
|
|
// there is never a need to use --conventional-commits cli option because the
|
|
|
|
|
// default behavior is `true`
|
|
|
|
|
if (args['conventional-commits'] === false) {
|
|
|
|
|
cCommits = false;
|
|
|
|
|
} else {
|
|
|
|
|
cCommits = DEFAULT_CONVENTIONAL_COMMITS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const DEFAULT_CONVENTIONAL_GRADUATE = false;
|
|
|
|
|
const cGraduate = args['conventional-graduate'] || DEFAULT_CONVENTIONAL_GRADUATE;
|
|
|
|
|
|
|
|
|
|
const DEFAULT_CONVENTIONAL_PRERELEASE = false;
|
|
|
|
|
const cPrerelease = args['conventional-prerelease'] || DEFAULT_CONVENTIONAL_PRERELEASE;
|
|
|
|
|
|
|
|
|
|
// if not using --no-create-release or --no-push cli option then an environment
|
|
|
|
|
// variable named GH_TOKEN must be defined with a properly scoped GitHub
|
|
|
|
|
// personal access token; for local releases, e.g. with verdaccio,
|
|
|
|
|
// --no-create-release should be used (unless using --no-push, which implies
|
|
|
|
|
// --no-create-release)
|
|
|
|
|
// See: https://github.com/lerna/lerna/tree/master/commands/version#--create-release-type
|
|
|
|
|
const DEFAULT_CREATE_RELEASE = true;
|
|
|
|
|
let createRelease;
|
|
|
|
|
// with --no-create-release cli option `args['create-release']` will be `false`
|
|
|
|
|
// there is never a need to use --create-release cli option because the default
|
|
|
|
|
// is `true`
|
|
|
|
|
if (args['create-release'] === false) {
|
|
|
|
|
createRelease = false;
|
|
|
|
|
} else {
|
|
|
|
|
createRelease = DEFAULT_CREATE_RELEASE;
|
|
|
|
|
}
|
|
|
|
|
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
const DEFAULT_DIST_TAG = `latest`;
|
|
|
|
|
const distTag = args['dist-tag'] || DEFAULT_DIST_TAG;
|
|
|
|
|
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
const DEFAULT_FORCE_PUBLISH = false;
|
|
|
|
|
const forcePublish = args['force-publish'] || DEFAULT_FORCE_PUBLISH;
|
|
|
|
|
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
const DEFAULT_GIT_REMOTE = `origin`;
|
|
|
|
|
const remote = args['git-remote'] || DEFAULT_GIT_REMOTE;
|
|
|
|
|
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
const DEFAULT_NO_PUSH = false;
|
|
|
|
|
let noPush;
|
|
|
|
|
// with --no-push cli option `args['push']` will be `false`
|
|
|
|
|
// there is never a need to use --push cli option because the default behavior
|
|
|
|
|
// is to push
|
|
|
|
|
if (args['push'] === false) {
|
|
|
|
|
noPush = true;
|
|
|
|
|
} else {
|
|
|
|
|
noPush = DEFAULT_NO_PUSH;
|
|
|
|
|
}
|
|
|
|
|
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
const DEFAULT_PRE_ID = null;
|
|
|
|
|
const preId = args.preid || DEFAULT_PRE_ID;
|
|
|
|
|
|
|
|
|
|
const DEFAULT_RELEASE_BRANCH = `master`;
|
|
|
|
|
const branch = args['release-branch'] || DEFAULT_RELEASE_BRANCH;
|
|
|
|
|
|
|
|
|
|
const DEFAULT_SIGN = false;
|
|
|
|
|
const sign = args.sign || DEFAULT_SIGN;
|
|
|
|
|
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
const DEFAULT_SKIP_QA = false;
|
|
|
|
|
const skipQa = args['skip-qa'] || DEFAULT_SKIP_QA;
|
|
|
|
|
|
|
|
|
|
const DEFAULT_VERSION_ONLY = false;
|
|
|
|
|
const versionOnly = args['version-only'] || DEFAULT_VERSION_ONLY;
|
|
|
|
|
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
const cyan = (str) => chalk.cyan(str);
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
const execSyncInherit = (cmd) => execSync(cmd, {stdio: 'inherit'});
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
const log = (mark, str, which = 'log') => console[which](
|
|
|
|
|
mark, str.filter(s => !!s).join(` `)
|
|
|
|
|
);
|
|
|
|
|
const logError = (...str) => log(chalk.red(`✘`), str, 'error');
|
|
|
|
|
const logInfo = (...str) => log(chalk.blue(`ℹ`), str);
|
|
|
|
|
const logSuccess = (...str) => log(chalk.green(`✔`), str);
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
const logWarning = (...str) => log(chalk.yellow('‼︎'), str);
|
|
|
|
|
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
const failMsg = `${chalk.red(`RELEASE FAILED!`)} Stopping right here.`;
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
const reportSetting = (desc, val, def) => {
|
|
|
|
|
logInfo(`${desc} is set to ${cyan(val)}${val === def ? ` (default).`: `.`}`);
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
};
|
|
|
|
|
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
const runCommand = (cmd, inherit = true, display) => {
|
|
|
|
|
logInfo(`Running command ${cyan(display || cmd)}.`);
|
|
|
|
|
let out;
|
|
|
|
|
if (inherit) {
|
|
|
|
|
execSyncInherit(cmd);
|
|
|
|
|
} else {
|
|
|
|
|
out = execSync(cmd);
|
|
|
|
|
}
|
|
|
|
|
return out;
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
(async () => {
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
if (!noPush && createRelease && !process.env.GH_TOKEN) {
|
|
|
|
|
logError(
|
|
|
|
|
`Environment variable ${cyan('GH_TOKEN')} was not defined or falsy. It`,
|
|
|
|
|
`must be defined with a properly scoped GitHub personal access token,`,
|
|
|
|
|
`or else the ${cyan('--no-create-release')} or ${cyan('--no-push')}`,
|
|
|
|
|
`option should be used. Always use ${cyan('--no-create-release')} when`,
|
|
|
|
|
`running a local release, e.g. with ${cyan('verdaccio')} (unless using`,
|
|
|
|
|
`${cyan('--no-push')}, which implies ${cyan('--no-create-release')}).`
|
|
|
|
|
);
|
|
|
|
|
logError(failMsg);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const lernaJsonPath = path.join(__dirname, '../lerna.json');
|
|
|
|
|
logInfo(`Reading ${cyan(lernaJsonPath)}...`);
|
|
|
|
|
|
|
|
|
|
let lernaJson;
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
try {
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
lernaJson = readJsonSync(lernaJsonPath);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(e.stack || e);
|
|
|
|
|
logError(
|
|
|
|
|
`Could not read ${cyan(lernaJsonPath)}. Please check the error above.`
|
|
|
|
|
);
|
|
|
|
|
logError(failMsg);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
let DEFAULT_REGISTRY, registry;
|
|
|
|
|
if (!versionOnly) {
|
|
|
|
|
try {
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
DEFAULT_REGISTRY = lernaJson.command.publish.registry;
|
|
|
|
|
if (!DEFAULT_REGISTRY) throw new Error('missing registry in lerna.json');
|
|
|
|
|
registry = args.registry || DEFAULT_REGISTRY;
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
} catch (e) {
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
console.error(e.stack || e);
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
logError(
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
`Could not read values from ${cyan(lernaJsonPath)}. Please check the`,
|
|
|
|
|
`error above.`
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
);
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
logError(failMsg);
|
|
|
|
|
process.exit(1);
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
}
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
}
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
logInfo(`Checking the working tree...`);
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
try {
|
|
|
|
|
runCommand(`npm run --silent cwtree`, true, `npm run cwtree`);
|
|
|
|
|
logSuccess(`Working tree is clean.`);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
logError(
|
|
|
|
|
`Working tree is dirty or has untracked files.`,
|
|
|
|
|
`Please make necessary changes or commits before rerunning this script.`
|
|
|
|
|
);
|
|
|
|
|
logError(failMsg);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
reportSetting(`Release branch`, branch, DEFAULT_RELEASE_BRANCH);
|
|
|
|
|
logInfo(`Determining the current branch...`);
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
let currentBranch;
|
|
|
|
|
try {
|
|
|
|
|
currentBranch = runCommand(`git rev-parse --abbrev-ref HEAD`, false)
|
|
|
|
|
.toString()
|
|
|
|
|
.trim();
|
|
|
|
|
} catch (e) {
|
|
|
|
|
logError(`Could not determine the branch. Please check the error above.`);
|
|
|
|
|
logError(failMsg);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
if (currentBranch === branch) {
|
|
|
|
|
logSuccess(`Current branch and release branch are the same.`);
|
|
|
|
|
} else {
|
|
|
|
|
logError(
|
|
|
|
|
`Current branch ${cyan(currentBranch)} is not the same as release`,
|
|
|
|
|
`branch ${cyan(branch)}. Please checkout the release branch before`,
|
|
|
|
|
`rerunning this script or rerun with`,
|
|
|
|
|
`${cyan(`--release-branch ${currentBranch}`)}.`
|
|
|
|
|
);
|
|
|
|
|
logError(failMsg);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
let localRef;
|
|
|
|
|
if (!noPush) {
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
reportSetting(`Git remote`, remote, DEFAULT_GIT_REMOTE);
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
logInfo(
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
`Fetching commits from ${cyan(remote)} to compare local and remote`,
|
|
|
|
|
`branches...`
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
try {
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
runCommand(`git fetch ${remote}`, false);
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
} catch (e) {
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
logError(`Could not fetch latest commits. Please check the error above.`);
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
logError(failMsg);
|
|
|
|
|
process.exit(1);
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
let remoteRef;
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
try {
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
localRef = runCommand(`git rev-parse ${branch}`, false).toString().trim();
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
remoteRef = runCommand(`git rev-parse ${remote}/${branch}`, false)
|
|
|
|
|
.toString()
|
|
|
|
|
.trim();
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
} catch (e) {
|
|
|
|
|
logError(`A problem occured. Please check the error above.`);
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
logError(failMsg);
|
|
|
|
|
process.exit(1);
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
if (localRef === remoteRef) {
|
|
|
|
|
logSuccess(`Local branch is in sync with remote branch.`);
|
|
|
|
|
} else {
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
logError(
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
`Local branch ${cyan(branch)} is not in sync with`,
|
|
|
|
|
`${cyan(`${remote}/${branch}`)}.`,
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
`Please sync branches before rerunning this script.`
|
|
|
|
|
);
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
logError(failMsg);
|
|
|
|
|
process.exit(1);
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
}
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
} else {
|
|
|
|
|
try {
|
|
|
|
|
localRef = runCommand(`git rev-parse ${branch}`, false).toString().trim();
|
|
|
|
|
} catch (e) {
|
|
|
|
|
logError(`A problem occured. Please check the error above.`);
|
|
|
|
|
logError(failMsg);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
if (skipQa) {
|
|
|
|
|
logWarning(
|
|
|
|
|
`Skipping the QA suite. You already built the packages, right?`
|
|
|
|
|
);
|
|
|
|
|
} else {
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
logInfo(
|
|
|
|
|
`It's time to run the QA suite, this will take awhile...`
|
|
|
|
|
);
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
|
|
|
|
|
try {
|
build: make DApp templates member packages of the monorepo
Previously, templates were in a subdirectory of `packages/embark`. Reorganize
them so that they are member packages of the monorepo. This allows them to
cleanly depend on other members of the monorepo,
e.g. `embarkjs-connector-web3`.
It is desirable for the templates, in the context of the monorepo, to specify
embark as a dependency, to take advantage of `npx embark test` (and it's a
"forward looking" setup re: how we plan to evolve embark). However, if embark
were to specify the template packages as dependencies a circular relationship
would be introduced, which is [unsupported by Lerna][circular]. Therefore,
revise the template generator so that all templates are resolved / fetched at
runtime, i.e. `boilerplate`, `demo`, and `simple` are no longer
"built-ins" *per se*. This change won't be apparent to embark's users, but it
does mean that the template generator won't work (in a production install of
embark) if it can't connect to the npm registry, i.e. when the user runs
`embark demo` or `embark new [--simple]`. When embark is inside the monorepo,
templates are resolved and copied from the yarn workspace rather than being
fetched from the registry, which is convenient for development. Also, any
template dependencies that are members of the monorepo are linked into the
copied template's `node_modules` rather than being installed from the registry,
again for convenience. During template generation, remove scripts and
dependencies that pertain only to membership in the monorepo; for now, that
involves removing embark as a dependency since we're not quite ready for that
arrangement to be the default, i.e. outside of the monorepo.
Refactor the root scripts so that more of them can consistently be used with
Lerna's filter options, e.g. `--scope` and `--ignore`. "Combo" scripts that
don't support filtering generally have a `:full` postfix.
Flip `clean` and `reset` scripts at the root and in the member packages for
consistency re: Lerna's notion of `clean` and embark's notion of `reset`. Have
each package run its `reset` script when its `clean` script is invoked (and
that's all for now), relying on `lerna clean` to delete packages'
`node_modules` in view of how Lerna's topological sorting works.
Lift the implementation of `embark reset` into a private package in
`packages/embark-reset` and make it a bundled dependency of embark. Packages in
`dapps/*` depend on `embark-reset` directly and make use of it with `npx
embark-reset` (but only in monorepo context). This removes a "wart" where
reboots could show errors when embark's sources aren't already built in
`packages/embark/dist`. Users will not notice any difference since `embark
reset` works as before, transparently making use of the `embark-reset`
package. The only downside to having it be a bundled dependency of embark is
that bundled deps have all of their `node_modules` included in the tarball
built with `npm pack` (that's why having the templates as bundled dependencies
of embark isn't a viable approach). However, `embark-reset` only has one
dependency, `rimraf`, which is a tiny module, so the cost seems acceptable.
As part of the reorganization, move `test_dapps` into `dapps/tests` and
`packages/embark/templates` into `dapps/templates`. Keep the directory names
short but revise the package names to facilitate simple filtering with
`embark-dapp-*`. Consolidate `.yarnrc` and `.gitignore` and clean up some
redundant ignore listings.
Scripts run with `--scope embark-dapp-*` use `--concurrency=1` to avoid
conflicts that could arise over network ports. The `ci:full` and `qa:full`
scripts use `--concurrency=1` in all scopes, for two reasons: resource
limitations on Travis and AppVeyor result in slower runs with concurrency >1,
and if something fails in those contexts it's easier to see what went wrong
when Lerna's output isn't interleaved from a bunch of scripts in `packages/*`.
Bump the Lerna version.
[circular]: https://github.com/lerna/lerna/issues/1198#issuecomment-442278902
2019-02-25 20:47:54 +00:00
|
|
|
|
runCommand(`npm run qa:full`);
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
logSuccess(`All steps succeeded in the QA suite.`);
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
} catch (e) {
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
logError(`A step failed in the QA suite. Please check the error above.`);
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
logError(failMsg);
|
|
|
|
|
process.exit(1);
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
}
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
}
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
logInfo(`${versionOnly ? 'Versioning' : 'Publishing'} with Lerna...`);
|
|
|
|
|
if (bump) reportSetting(`Version bump`, bump, DEFAULT_BUMP);
|
|
|
|
|
reportSetting(`Conventional commits option`, cCommits, DEFAULT_CONVENTIONAL_COMMITS);
|
|
|
|
|
reportSetting(`Conventional graduate option`, cGraduate, DEFAULT_CONVENTIONAL_GRADUATE);
|
|
|
|
|
reportSetting(`Conventional prerelease option`, cPrerelease, DEFAULT_CONVENTIONAL_PRERELEASE);
|
|
|
|
|
if (!noPush) reportSetting(`Create GitHub release option`, createRelease, DEFAULT_CREATE_RELEASE);
|
|
|
|
|
if (!versionOnly) reportSetting(`NPM dist-tag`, distTag, DEFAULT_DIST_TAG);
|
|
|
|
|
reportSetting(`Force publish option`, forcePublish, DEFAULT_FORCE_PUBLISH);
|
|
|
|
|
reportSetting(`Commit message format`, commitMsg, DEFAULT_COMMIT_MSG);
|
|
|
|
|
reportSetting(`No push option`, noPush, DEFAULT_NO_PUSH);
|
|
|
|
|
if (preId) reportSetting(`Prerelease identifier`, preId, DEFAULT_PRE_ID);
|
|
|
|
|
if(!versionOnly) reportSetting(`Package registry`, registry, DEFAULT_REGISTRY);
|
|
|
|
|
reportSetting(`Signature option`, sign, DEFAULT_SIGN);
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
const lernaCmd = [
|
|
|
|
|
`lerna`,
|
|
|
|
|
(versionOnly && `version`) || `publish`,
|
|
|
|
|
bump || ``,
|
|
|
|
|
(cCommits && `--conventional-commits`) || ``,
|
|
|
|
|
(cCommits && cGraduate && `--conventional-graduate${cGraduate === true ? '' : `=${cGraduate}`}`) || ``,
|
|
|
|
|
(cCommits && cPrerelease && `--conventional-prerelease${cPrerelease === true ? '' : `=${cPrerelease}`}`) || ``,
|
|
|
|
|
(!noPush && createRelease && `--create-release github`) || ``,
|
|
|
|
|
(!versionOnly && `--dist-tag ${distTag}`) || ``,
|
|
|
|
|
(forcePublish && `--force-publish${forcePublish === true ? '' : `=${forcePublish}`}`) || ``,
|
|
|
|
|
(!noPush && `--git-remote ${remote}`) || ``,
|
|
|
|
|
`--message "${commitMsg}"`,
|
|
|
|
|
(noPush && `--no-push`) || ``,
|
|
|
|
|
(preId && `--preid ${preId}`) || ``,
|
|
|
|
|
(!versionOnly && `--registry ${registry}`) || ``,
|
|
|
|
|
(sign && `--sign-git-commit`) || ``,
|
|
|
|
|
(sign && `--sign-git-tag`) || ``
|
|
|
|
|
].filter(str => !!str).join(` `);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
runCommand(lernaCmd);
|
|
|
|
|
if (bump !== 'from-package' && localRef ===
|
|
|
|
|
runCommand(`git rev-parse ${branch}`, false).toString().trim()) {
|
|
|
|
|
let action, cmd, noPubMsg;
|
|
|
|
|
if (versionOnly) {
|
|
|
|
|
action = 'version creation';
|
|
|
|
|
cmd = 'version';
|
|
|
|
|
noPubMsg = '';
|
|
|
|
|
} else {
|
|
|
|
|
action = 'publication';
|
|
|
|
|
cmd = 'publish';
|
|
|
|
|
noPubMsg = `No packages were published. `;
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
}
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
logWarning(
|
|
|
|
|
chalk.yellow(`RELEASE STOPPED!`),
|
|
|
|
|
`No commit or tag was created. ${noPubMsg}Please check the output`,
|
|
|
|
|
`above if you did not stop ${action} via a prompt from the`,
|
|
|
|
|
`${cyan(`lerna ${cmd}`)} command.`
|
|
|
|
|
);
|
|
|
|
|
process.exit(0);
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
logError(`A problem occured. Please check the error above.`);
|
|
|
|
|
let checkPkgMsg;
|
|
|
|
|
if (versionOnly) {
|
|
|
|
|
checkPkgMsg = '';
|
|
|
|
|
} else {
|
|
|
|
|
const lernaDocsUrl = 'https://github.com/lerna/lerna/tree/master/commands/publish#bump-from-package';
|
|
|
|
|
checkPkgMsg = [
|
|
|
|
|
` Check the package registry to verify if any packages were published.`,
|
|
|
|
|
`If so they may need to be flagged as deprecated since the`,
|
|
|
|
|
`${cyan(`lerna publish`)} command exited with error. In some cases it`,
|
|
|
|
|
`may be possible to salvage an imcomplete release by using the`,
|
|
|
|
|
`${cyan('from-package')} keyword with the ${cyan('lerna publish')}`,
|
|
|
|
|
`command. See: ${lernaDocsUrl}`
|
|
|
|
|
].join(' ');
|
|
|
|
|
}
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
logError(
|
build: implement a monorepo with Lerna
TL;DR
=====
`yarn install` in a fresh clone of the repo.
`yarn reboot` when switching branches.
When pulling in these changes, there may be untracked files at the root in
all/some of:
```
.embark/
.nyc_output/
coverage/
dist/
embark-ui/
test_apps/
```
They can be safely deleted since those paths are no longer in use at the root.
Many of the scripts in the top-level `package.json` support Lerna's [filter
options]. For example:
`yarn build --scope embark` build only `packages/embark`.
`yarn build --ignore embark-ui` build everything except `packages/embark-ui`.
Scoping scripts will be more useful when there are more packages in the
monorepo and, for example, `yarn start` doesn't need to be invoked for all of
them while working on just a few of them simultaneously, e.g `embark` and
`embarkjs`.
It's also possible to `cd` into a particular package and run its scripts
directly:
```
cd packages/embark && yarn watch
```
Hot Topics & Questions
======================
What should be done about the [README][embark-readme] for `packages/embark`?
Should the top-level README be duplicated in that package?
Lerna is setup to use [Fixed/Locked mode][fixed-locked], and accordingly
`packages/embark-ui` is set to `4.0.0-beta.0`. The same will be true when
adding embarkjs, swarm-api, etc. to the monorepo. Is this acceptable or do we
want to use [Independent mode][independent]?
Scripts
=======
If a package doesn't have a matching script, `lerna run` skips it
automatically. For example, `packages/embark-ui` doesn't have a `typecheck`
script.
`yarn build`
------------
Runs babel, webpack, etc. according to a package's `build` script.
`yarn build:no-ui` is a shortcut for `yarn build --ignore embark-ui`.
`yarn ci`
---------
Runs a series of scripts relevant in a CI context according to a package's `ci`
script. For `packages/embark` that's `lint typecheck build test package`.
Also runs the `ci` script of the embedded `test_dapps` monorepo.
`yarn clean`
------------
Runs rimraf, etc. according to a package's `clean` script.
`yarn globalize`
----------------
Makes the development embark available on the global PATH, either via
symlink (Linux, macOS) or a shim script (Windows).
`yarn lint`
-----------
Runs eslint, etc. according to a package's `lint` script.
`yarn package`
--------------
Invokes `npm pack` according to a package's `package` script.
`yarn qa`
---------
Very similar to `ci`, runs a series of scripts according to a package's `qa`
script. The big difference between `ci` and `qa` is that at the top-level `qa`
first kicks off `reboot:full`.
There is a `preqa` script ([invoked automatically][npm-scripts]), which is a
bit of a wart. It makes sure that `embark reset` can be run successfully in
`packages/embark/templates/*` when the `reboot` script invokes the `reset`
script.
The `qa` script is invoked by `yarn release` before the latter proceeds to
invoke `lerna publish`.
`yarn reboot`
-------------
Invokes the `reset` script and then does `yarn install`.
The `reboot:full` variant invokes `reset:full` and then does `yarn install`.
`yarn release`
--------------
Works in concert with [lerna publish], which will prompt to verify the version
before proceeding. Use `n` to cancel instead of `ctrl-c` as `lerna publish` has
been seen to occasionally misbehave when not exited cleanly (e.g. creating a
tag when it shouldn't have).
```
yarn release [bump] [--options]
```
* `[bump]` see [`publish` positionals][pub-pos] and [`version`
positionals][ver-pos]; an exact version can also be specified.
* `--preid` prerelease identifier, e.g. `beta`; when doing a prerelease bump
will default to whatever identifier is currently in use.
* `--dist-tag` registry distribution tag, defaults to `latest`.
* `--message` commit message format, defaults to `chore(release): %v`.
* `--sign` indicates that the git commit and tag should be signed; not signed
by default.
* `--release-branch` default is `master`; must match the current branch.
* `--git-remote` default is `origin`.
* `--registry` default is `https://registry.npmjs.org/` per the top-level
[`lerna.json`][lerna-json].
To release `4.0.0-beta.1` as `embark@next` (assuming version is currently at
`4.0.0-beta.0`) could do:
```
yarn release prerelease --dist-tag next
```
For *test releases* (there is no longer a `--dry-run` option) [verdaccio] and a
filesystem git remote can be used.
Condensend instructions:
```
mkdir -p ~/temp/clones && cd ~/temp/clones
git clone git@github.com:embark-framework/embark.git
cd ~/repos/embark
git remote add FAKEembark ~/temp/clones/embark
```
in another terminal:
```
npm i -g verdaccio && verdaccio
```
in the first terminal:
```
yarn release --git-remote FAKEembark --registry http://localhost:4873/
```
`yarn reset`
------------
Invokes cleaning and resetting steps according to a package's `reset`
script. The big difference between `clean` and `reset` is that `reset` is
intended to delete a package's `node_modules`.
The `reset:full` variant deletes the monorepo's top-level `node_modules` at the
end. That shouldn't be necessary too often, e.g. in day-to-day work when
switching branches, which is why there is `reboot` / `reset` vs. `reboot:full`
/ `reset:full`.
Errors may be seen related to invocation of `embark reset` if embark is not
built, but `reset` will still complete successfully.
`yarn start`
------------
Runs babel, webpack, tsc, etc. (in parallel, in watch mode) according to a
package's `start` script.
`yarn test`
-----------
Run mocha, etc. according to a package's `test` script.
The `test:full` variant runs a series of scripts: `lint typecheck test
test_dapps`.
`yarn test_dapps`
-----------------
Runs the `test` script of the embedded `test_dapps` monorepo.
The `test_dapps:ci` and `test_dapps:qa` variants run the `ci` and `qa` scripts
of the embedded `test_dapps` monorepo, respectively.
`yarn typecheck`
----------------
Runs tsc, etc. according to a package's `typecheck` script.
Notes
=====
`npx` is used in some of the top-level and package scripts to ensure the
scripts can run even if `node_modules` is missing.
[`"nohoist"`][nohoist] specifies a couple of embark packages because
[`restrictPath`][restrictpath] is interfering with access to modules that are
located in a higher-up `node_modules`.
All dependencies in `packages/embark-ui` have been made `devDependencies` since
its production build is self-contained.
`packages/embark`'s existing CHANGELOG's formatting has been slightly adjusted
to match the formatting that Lerna will use going forward (entries in the log
haven't been modified).
Lerna will generate a CHANGELOG at the top-level and in each package. Since
we're transitioning to a monorepo, things may look a little wonky with respect
to old entries in `packages/embark/CHANGELOG.md` and going forward we need to
consider how scoping our commits corresponds to member-packages of the
monorepo.
In `packages/embark`, `test` invokes `scripts/test`, which starts a child
process wherein `process.env.DAPP_PATH` is a temporary path that has all of
`packages/embark/dist/test` copied into it, so that paths to test
helpers/fixtures don't need to be prefixed with `dist/test/` and so that a
`.embark` directory doesn't get written into `packages/embark`.
The `"engines"` specified in top-level and packages' `package.json` reflect a
node and npm pair that match (a source of confusion in the past). The pair was
chosen according to the first post v5 npm that's bundled with node. A
`"runtime"` key/object has been introduced in `packages/embark/package.json`
which is used as the basis for specifying the minimum version of node that can
be used to run embark, and that's what is checked by `bin/embark`.
Some changes have been introduced, e.g. in `lib/core/config` and
`lib/utils/solidity/remapImports` so that it's *not* implicitly assumed that
`process.env.DAPP_PATH` / `fs.dappPath()` are the same as
`process.cwd()`. There are probably several++ places where that assumption is
still in effect, and we should work to identify and correct them.
`embark reset` now deletes `embarkArtifacts/` within a dapp root, and
`embarkArtifacts/` is git-ignored.
`lib/core/env` adds all `node_modules` relative to `process.env.EMBARK_PATH` to
`NODE_PATH` so that embark's modules can be resolved as expected whether
embark's `node_modules` have been deduped or are installed in npm's flat
"global style".
`checkDependencies` has been inlined (see `lib/utils/checkDependencies`) and
slightly modified to support dependencies that have been hoisted into a
higher-up `node_modules`, e.g. as part of a yarn workspace. eslint has been
disabled for that script to avoid more involved changes to it.
`test_apps` is not in `packages/embark`; rather, there is `test_dapps` at the
top-level of the monorepo. `test_dapps` is an embedded monorepo, and its `ci` /
`qa` scripts `npm install` embark from freshly built tarballs of the packages
in the outer monorepo and then use that installation to run `embark test` in
the dapps. This should allow us to rapidly detect breakage related to
auto-bumps in transitive dependencies.
[filter options]: https://github.com/lerna/lerna/tree/master/core/filter-options
[embark-readme]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/README.md
[fixed-locked]: https://github.com/lerna/lerna#fixedlocked-mode-default
[independent]: https://github.com/lerna/lerna#independent-mode
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[lerna publish]: https://github.com/lerna/lerna/tree/master/commands/publish
[pub-pos]: https://github.com/lerna/lerna/tree/master/commands/publish#positionals
[ver-pos]: https://github.com/lerna/lerna/tree/master/commands/version#positionals
[lerna-json]: https://github.com/embark-framework/embark/blob/build/lerna/lerna.json#L11
[verdaccio]: https://www.npmjs.com/package/verdaccio
[nohoist]: https://github.com/embark-framework/embark/blob/build/lerna/package.json#L52-L55
[restrictpath]: https://github.com/embark-framework/embark/blob/build/lerna/packages/embark/src/lib/core/fs.js#L9
2019-01-28 18:15:05 +00:00
|
|
|
|
failMsg,
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
`Make sure to clean up the working tree and local/remote commits, tags,`,
|
|
|
|
|
`and releases as necessary.${checkPkgMsg}`
|
build: introduce a `prepare` script in embark's package.json
**TL;DR**
These changes affect workflow with yarn. To prevent embark's `prepare` script
from running undesirably:
- If node_modules is in place and you're reinstalling after switching branches:
```
yarn run install_all
```
- If node_modules is missing (fresh clone or deleted):
```
EMBARK_NO_PREPARE=t yarn install && yarn run install_all
```
It's not recommended to set `EMBARK_NO_PREPARE` in your environment (e.g. in
`.bashrc`) since that would interfere with embark's `release` script if/when
you run it.
-----------------
**1.** Specify embark's build-related steps in the `prepare` script of
package.json.
When embark is installed directly from GitHub the `prepare` script results in a
"pre install" phase (handled automatically by npm/yarn) that fetches
devDependencies, builds embark (including embark-ui), packs a tarball with the
same steps (minus testing and tree-checking) as would happen during an embark
release, and finally does a production install from that tarball.
Important point: installs from GitHub must be performed with yarn; they're no
longer possible with npm since during the "pre install" phase npm will honor
embark's `.npmrc` and `"engines"` settings.
The following will work correctly after this commit is merged:
```
yarn [global] add git+https://github.com/embark-framework/embark.git
```
Use of "hosted git" shortcuts (e.g. `embark-framework/embark#bracnh`) won't
work correctly because yarn doesn't fully support them. See:
https://github.com/yarnpkg/yarn/issues/5235.
It's important to use `git+https` urls. Following a succesful install with
`git+https` it is possible to use a "hosted git" shortcut or `https` url, but
that's owing to a subtle and unreliable interaction between yarn's cache and
yarn's logic for installing from a url/shortcut.
**2.** Adjust the npm configs (`.npmrc`) for embark/-ui so that `yarn run [cmd]
[--opt]` can be used in place of `npm run [cmd] -- [--opt]`.
Either way is okay for running scripts, they're equivalent, but note the
requirement to use `--` before specifying command options with `npm run`.
**3.** Introduce yarn configs (`.yarnrc`) for embark/-ui and include the
`check-files` directive.
H/t to @alaibe for the recommendation.
**4.** Ignore embark's `dist/typings` and `scripts` directories when packing a
tarball.
**5.** Refactor embark/-ui's npm-scripts in relation to the `prepare` script,
and make other small improvements.
Notably, if the environment variable `EMBARK_NO_PREPARE` is truthy (from JS
perspective) then embark's `prepare` script will exit early. This prevents
`install_all` and `prepare` from getting stuck in a loop (`install:core` uses
cross-env to set `EMBARK_NO_PREPARE`) and provides a mechanism for users to
skip the `prepare` script when doing a fresh install:
```
EMBARK_NO_PREPARE=t yarn install
```
**6.** Give `.js` extensions to node scripts in embark's `scripts/`, remove the
shebang lines, and have npm-scripts explicitly invoke them with node.
This arrangement works for all platforms: Linux, macOS, and Windows.
**7.** Adjust travis and appveyor configs.
Since at present there aren't any tests or other CI steps that make use of
embark-ui's production build, set `EMBARK_NO_PREPARE` in the CI environments
and invoke `build:node` directly.
Check the working tree after `yarn install` for embark/-ui. This detects
situations where changes should have been committed to `yarn.lock` but were
not. Check the working tree again at the end to detect situations where ignore
files should have been adjusted but were not. Both checks could also detect
other surprising behavior that needs to be investigated. Any time the working
tree is not clean (there are untracked files or changes) CI will fail.
Drop CI runs for node 8.11.3 because that version ships with an older npm that
results in unstaged changes to the test apps' `package-lock.json` files,
causing the working tree check to fail at the end of the CI run. A simple
workaround isn't apparent, but the matter can be revisited.
**8.** Refactor embark's `release` script in light of the `prepare` script.
Notably, do the push step only after `npm publish` completes successfully. This
allows embark's `prepare` and `prepublishOnly` scripts to detect problems
before a commit and tag are pushed to GitHub, avoiding a need to rebase/revert
the remote release branch; the local branch will still need to have a commit
dropped and tag deleted before rerunning the `release` script.
Prompt the user if the `release` script is not being run in `--dry-run` mode.
Provide additional visual indicators of `--dry-run` mode.
Force the user to supply `--repo-branch [branch]` if the intention is to
release from a branch other than `master`.
2018-11-19 19:11:57 +00:00
|
|
|
|
);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
ci: implement a nightlies GitHub Actions workflow
Implement a GitHub Actions workflow in `.github/workflows/nightlies.yml` named
*Nightlies*, which is scheduled to run once daily at 00:00 UTC.
At present the workflow includes one job named *release*, which is responsible
for publishing prerelease GitHub releases and NPM packages. Each prerelease
created (per package) will have a `nightly` [semver identifier][preid], and
each successive nightly release will be paired with the `nightly`
[dist-tag][dist-tag] on the NPM registry (per package).
During the release job, actions taken in this GitHub repository (commits, tags,
releases) and on the NPM registry (package publication) will be performed using
credentials associated with the following accounts:
* https://github.com/embarkbot
* https://www.npmjs.com/~embarkbot
For that purpose, corresponding [secrets][secrets] (link requires admin access)
were created in this repository consisting of API tokens generated for the
@embarkbot GitHub and NPM accounts. Logins for the @embarkbot accounts
themselves are protected by 2FA.
Implement `scripts/nightly-release.js` (`npm run release:nightly`), which is
responsible for running `lerna publish` in the GitHub Actions workflow. Also
implement `scripts/stable-release.js` (`npm run release:stable`), which is
intended to be run locally by someone on the Embark Team. Both scripts borrow
heavily from the existing `scripts/release.js`, and the process of authoring
and experimenting with them influenced refactors to the latter.
Use a `--force-publish` major-release strategy to prevent major-version drift
between packages in the monorepo. How it works: when the stable-release script
is run (`npm run release:stable`), if the current prerelease version involves a
major version increase relative to the most recent stable release then **all**
packages are bumped to the new major stable version. Otherwise, only the
packages currently in prerelease are graduated to the new minor/patch stable
version. In either case, the `nightly` dist-tag of each package published is
updated to resolve to the new stable version.
The reason for adopting this strategy *(a decision which can be revisited and
changed any time in the future)* is based on a concern that downstream users
would have a confusing developer UX if across `embark-*` packages there are
differing major versions.
To understand how the major-version drift would happen, consider the following
hypothetical scenario where `--force-publish` *isn't* used in stable releases
and `nightly` dist-tags aren't updated to resolve to the latest stable version:
assume the current stable version is `6.5.4`. A breaking change lands for
`embark-core`. The next nightly release bumps `embark-core` and about 40 other
packages to `7.0.0-nightly.0`. However, `embark-utils` (and others) isn't
bumped because it doesn't depend on `embark-core`. Later, without any
intervening changes to `embark-utils`, the prerelease is graduated so that
`embark-core`, etc. bump to `7.0.0`. So then some `embark-*` packages are at
major version `7` while others are still at `6`. *Note* that this is the case
even though this monorepo uses Lerna's *"fixed"* versioning mode. Inside the
monorepo, `lerna` makes sure that everything is okay, i.e. with respect to
automatically updating dependents' version specifiers for their dependencies
that are within the monorepo. But for downstream users things are a bit more
complex. If someone wanted to use `embark-utils` on its own and specified
`^7.0.0` as the version range (after observing that `embark` itself is in a
`7.x` series) it won't work because `embark-utils` is still in `6.x`. In the
general case, users may have to manually cross-check major versions of various
`embark-*` packages that they specify in their projects' `package.json`
files. There are tools like [npm-check-updates][ncu] that can make the task
easier, but there is still likely to be some confusion, especially given the
large and growing number of packages in this monorepo. Another area of
confusion would exist around the `nightly` dist-tag. In the scenario above,
`embark-core@nightly` (and/or `@nightly` of its dependents, e.g. `embark`)
would resolve to `7.0.0-nightly.0` but `embark-utils@nightly` would resolve to
some `6.5.4-nightly.N` (:bomb:), i.e. a prerelease version that predates the
current stable `6.5.4` release of `embark-utils` (and *might* not include all
changes that landed in `embark-utils` prior to that stable release).
By bumping all packages each time there is a major stable release, and by
having the `nightly` dist-tag always point to a package's most recent
release (whether stable or prerelease), the problems described above are
avoided.
To see the `--force-publish` major-release strategy in action take a look at
the [commit history][history] for the
[nightly-release-workflow-tester][mb-nrwt] repo together with the *Versions*
tab of the NPM pages for the [foo][foo], [bar][bar], [baz][baz], and
[quux][quux] packages. Ignore the version history for `<= 2.0.1` because those
pre/releases were made with a different strategy than the current one.
Refactor the existing `scripts/release.js` to make it more flexible generally
and with respect to options that can be forwarded to `lerna`. In particular,
it's now possible to run `lerna version` instead of `lerna publish` (the
default behavior) by using the `--version-only` cli option; when combining that
usage with `--skip-qa` and `--no-push` it's possible to conveniently and
quickly experiment with the [`bump` positional][bump] and additional options
such as `--force-publish`, `--conventional-prerelease`, and
`--conventional-graduate`, i.e. to better understand how `lerna` will update
package versions. That ability should make it much simpler to figure out the
best course of action to take locally (manually) when a nightly release
completely or partially failed (which could happen for a number of reasons), as
well for other scenarios such as making a minor/patch release in a previous
line of major releases, or when making two/more successive stable releases
without a nightly release having happened in the meantime.
An important change to `scripts/release.js` is that by default it makes use of
the `--create-release github` option for `lerna version|publish`. For that to
work, an environment variable named `GH_TOKEN` must be defined with a properly
[scoped][scopes] GitHub [personal access token][pa-token] (`public_repo` scope
is sufficient for creating releases). The same is true for
`scripts/stable-release.js`.
Delete the `.github/PULL_REQUEST_TEMPLATE` directory and the templates it
contained. Unlike for GitHub issue creation, there is no prompt-page for
picking from a repo's PR templates; to use a PR template a `template=[name]`
[query parameter][template-query] must be appended to the URL of the PR
creation page. So the PR templates ended up unused by the Embark Team and
external contributors because it's not convenient to use them. Restore the
default PR template we had in place some time ago (with some small revisions)
since it seems like a helpful starting point, especially for external
contributors. Consistently use all-lowercase filenames for ISSUE/PR templates.
[preid]: https://semver.org/#spec-item-9
[dist-tag]: https://docs.npmjs.com/cli/dist-tag
[secrets]: https://github.com/embarklabs/embark/settings/secrets
[ncu]: https://www.npmjs.com/package/npm-check-updates
[history]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/commits/master
[mb-nrwt]: https://github.com/michaelsbradleyjr/nightly-release-workflow-tester/
[foo]: https://www.npmjs.com/package/nightly-release-workflow-tester-foo?activeTab=versions
[bar]: https://www.npmjs.com/package/nightly-release-workflow-tester-bar?activeTab=versions
[baz]: https://www.npmjs.com/package/nightly-release-workflow-tester-baz?activeTab=versions
[quux]: https://www.npmjs.com/package/nightly-release-workflow-tester-quux?activeTab=versions
[bump]: https://github.com/lerna/lerna/tree/master/commands/version#semver-bump
[scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/
[pa-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
[template-query]: https://help.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository
2020-01-07 17:09:38 +00:00
|
|
|
|
|
|
|
|
|
logSuccess(`${chalk.green(`RELEASE SUCCEEDED!`)} Woohoo! Done.`);
|
|
|
|
|
})().then(() => {
|
|
|
|
|
process.exit(0);
|
|
|
|
|
}).catch(e => {
|
|
|
|
|
console.error(e.stack || e);
|
|
|
|
|
logError(`A problem occured. Please check the error above.`);
|
|
|
|
|
logError(failMsg);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
});
|