Contributions to KeystoneJS in the form of issues and PRs are welcomed.
During the alpha stage of development we are focussing on getting the core systems working smoothly. Contributions which improve the documentation and test coverage are particularly welcomed.
Keystone makes no assumptions about type of applications it powers. It achieves flexibility through small, highly composable parts that allow you to build a foundation for any type of application.
For this reason we might not add features to Keystone if they are prescriptive about:
- Data structures
- Workflows
- Access controls
- Front-end application UI
But we want your contributions! We recognise many types of applications share common features and prescriptive patterns can sometimes be helpful, even at the expense of flexibility.
If you develop custom fields, adapters, apps or any other Keystone feature, (or have an idea) join us on the Keystone Slack channel or make a pull request to KeystoneJS-Contrib and we will add it to our list of community libraries.
KeystoneJS adheres to the Contributor Covenant Code of Conduct.
Keystone uses @noviny's @changesets/cli in combination with bolt
to track package versions and publish packages.
This tool allows each PR to indicate which packages need a version bump along with a changelog snippet.
This information is then collated when performing a release to update package versions and CHANGELOG.md
files.
- Make your changes (as per usual)
- Before you make a Pull Request, run the
bolt changeset
command and answer the questions that are asked. It will want to know:- which packages you want to publish
- what version you are releasing them at
- a message to summarise the changes (this message will be written to the changelog of bumped packages)
- Before you accept the changeset, it will inform you of any other dependent packages within the repo that will also be bumped by this changeset. If this looks fine, agree, and a changeset will be generated in the
.changeset
directory.
Each changeset contains two files; changes.json
, which contains structured data which indicates the packages which need to be updated, and changes.md
, which contains a markdown snippet which will be included in the CHANGELOG.md
files for the updated packages.
Here is what a changeset.json
looks like:
{
"releases": [
{ "name": "@keystone-alpha/adapter-mongoose", "type": "patch" },
{ "name": "@keystone-alpha/keystone", "type": "minor" }
],
"dependents": []
}
An example, if you generate a changeset that includes adapter-mongoose
as a patch, and keystone
as a minor, you can merge your PR, and the next time the version-packages
command is run, these will both be updated.
You can have multiple changesets in a single PR. This will give you more granular changelogs, and is encouraged.
This should only ever be done by a very short list of core contributors
Releasing is a two-step process. The first step updates the packages, and the second step publishes updated packages to npm.
The first step is bolt version-packages
. This will find all changesets that have been created since the last release, and update the version in package.json as specified in those changesets, flattening out multiple bumps to a single package into a single version update.
The bolt version-packages
command will generate a release commit, which will bump all versions, necessary dependency version changes, and update changelog.mds.
The commands to run are:
git checkout master && \
git pull && \
git branch -D temp-release-branch && \
git checkout -b temp-release-branch && \
bolt fresh && \
bolt build && \
bolt version-packages && \
bolt format && \
git add . && \
git commit -m "Prepare release" && \
git push --set-upstream origin temp-release-branch
Once you have run this you will need to make a pull request to merge this back into master.
Once the version changes are merged back in to master, to do a manual release:
git checkout master && \
git pull && \
bolt && \
bolt publish-changed && \
git push --tags && \
bolt
The bolt publish-changed
command finds packages where the version listed in the package.json
is ahead of the version published on npm, and attempts to publish just those packages.
Because of this, we should keep the following in mind:
- Once the
publish-changed
command has been run, the PR from thetemp-release-branch
should be merged before any other PRs are merged into master, to ensure that no changesets are skipped from being included in a release. - There is no reason you should ever manually edit the version in the
package.json
The release process will automatically generate and update a CHANGELOG.md
file, however this does not need to be the only way this file is modified. The changelogs are deliberately static assets so past changelogs can be updated or expanded upon.
In addition, content added above the last released version will automatically be appended to the next release. If your changes do not fit comfortably within the summary of a changelog, we encourage you to add a more detailed account directly into the CHANGELOG.md
.
Some of the packages in keystone-5 need to compiled before they're published, we use preconstruct to do this.
Preconstruct reads from the packages.json
preconstruct field for configuration, in keystone-5 all we need to do is set the packages that we need to build. Preconstruct reads all of the packages specified in the packages and checks the main
and module
fields and generates compiled versions. Preconstruct under the hood uses rollup to bundle all of the modules together which means people can't expose and interact with the modules (e.g. to change internals that could change in a patch version), it's also results in smaller builds because rollup is better at tree shaking than webpack. Preconstruct also uses babel and reads from the babel config in the repo to compile the code, there is one important babel plugin that Preconstruct adds which is @babel/plugin-transform-runtime
which tells babel to import the helpers that it uses in generated code from a certain place rather than duplicating them in each package.
Preconstruct can generate a couple different types of modules, in keystone-5, we build esm and commonjs modules.
ESM bundles are built for newer bundlers like parcel, rollup and newer versions of webpack which understand ES modules and can build more optimised bundles from them than they can with commonjs.
We also build commonjs builds to run in node (for testing with jest or etc.) and for bundlers which don't understand esm. Preconstruct generates three files for commonjs, a production, development and a file to import those modules. The production one compiles out process.env.NODE_ENV !== 'production'
checks which are common in front end libraries but process.env.NODE_ENV
is expensive to check in node if it happens very often.
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!