This is documentation for maintainers of this project.
Please review, understand, and be an example of it. Violations of the code of conduct are taken seriously, even (especially) for maintainers.
We want to support and build the community. We do that best by helping people learn to solve their own problems. We have an issue template and hopefully most folks follow it. If it's not clear what the issue is, invite them to create a minimal reproduction of what they're trying to accomplish or the bug they think they've found.
Once it's determined that a code change is necessary, point people to makeapullrequest.com and invite them to make a pull request. If they're the one who needs the feature, they're the one who can build it. If they need some hand holding and you have time to lend a hand, please do so. It's an investment into another human being, and an investment into a potential maintainer.
Remember that this is open source, so the code is not yours, it's ours. If someone needs a change in the codebase, you don't have to make it happen yourself. Commit as much time to the project as you want/need to. Nobody can ask any more of you than that.
As a maintainer, you're fine to make your branches on the main repo or on your own fork. Either way is fine.
When we receive a pull request, a GitHub Actions build is kicked off
automatically (see .github/workflows
). We usually avoid merging anything
that fails our Actions workflows.
Please review PRs and focus on the code rather than the individual. You never know when this is someone's first ever PR and we want their experience to be as positive as possible, so be uplifting and constructive.
When you merge the pull request, you should do so via either the rebase and merge or squash and merge features. This keeps our git history clean.
If commit messages need to be adjusted, maintainers should force push new commits with adjusted messages to the PR branch before merging it in.
Caution
Always favor rebase over squash for large and/or complex contributions since squashing commits may damage the generated CHANGELOG.md, hinder bisection, yield non-atomic commits, and could even result in the wrong version being released.
Our releases are automatic. They happen whenever certain commits are pushed to a relevant branch. That means a new release is generated only when there are useful changes to justify it. See the release rules for a list of commit types that trigger releases.
To generate a new release, a GitHub Actions build gets kicked off and, if it's successful, xrelease is used to automatically publish a new release to npm and GitHub along with an updated changelog. xrelease determines whether a release is necessary, and what the new version number will be, by analyzing git commit messages. With this in mind, it is imperative you brush up on the commit message convention which drives our releases.
Important
UNDER NO CIRCUMSTANCES should any of your commit messages contain the
strings BREAKING:
, BREAKING CHANGE:
, or BREAKING CHANGES:
unless the
goal is to release a new major version.
This project employs an automated CI/CD release pipeline. However, sometimes things get messed up (e.g. CI workflow / GitHub Actions breaks) and we need to trigger a release ourselves. When this happens, xrelease can be triggered locally.
Caution
Note that any manual releases generated outside of the CI/CD pipeline will be published without established provenance! It is for that reason that, outside of truly exceptional events, manual releases should be avoided at all costs.
Before proceeding with a manual release, first ensure all dependencies are installed and all necessary secrets are available.
Tip
You only need to run the following commands if you have not run npm install
at least once.
Important
These command should only be run at the project root level and not in any individual package root.
# 1. Install dependencies and add your auth tokens to the .env file.
#
# ! DO NOT COMMIT THE .env FILE !
cp .env.default .env
npm ci
To release all packages in a repository:
# Do a dry run first if you're not absolutely sure all is as it should be:
npx run release:topological -- --options --dry-run
# Then do the actual topological release:
npx run release:topological
To release a specific package (without regard for topology):
# Do a dry run first if you're not absolutely sure all is as it should be:
npx -w specific-package-name-here run release -- --dry-run
# Then do the actual topological release:
npx -w specific-package-name-here run release
Warning
Note that, in a monorepo/hybridrepo, relying on these commands to manually cut a release may result in a non-functional package being released if said package depends on other packages in the project that have unreleased changes.
Symbiote's "project topology" command solves this problem and should be preferred over building packages individually.
There are two ways to execute the release procedure of a particular package by hand. The first is by leveraging the release script:
# Do a symbiote dry run first:
npm run release -- --dry-run
# Then do the actual symbiote-based release:
npm run release
Note
See npx symbiote release --help
for more options.
The second way is by running the following npm scripts in the specified order:
Warning
If one of these steps fails, you should address the failure before running the next step.
Tip
These commands should be run with the root of the individual package you're
trying to release as the current working directory. Using npm -w
also works.
# 2. OPTIONAL: Reset the working tree to a clean state. The build command
# usually does this for you, making this step unnecessary.
#npm run clean -- --force
# 3. Format this package's files.
npm run format
# 4. Lint every file in the package and any files imported by those files.
npm run lint:package
# 5. Build this package's distributables.
npm run build
# 6. Build this package's documentation (AFTER format for correct line numbers).
npm run build:docs
# 7. Run all of this package's tests and the tests of any package imported by
# source files in this package, then generate coverage data.
npm run test:package:all
# 8. Trigger xrelease locally to publish a new release of this package. This
# requires having valid tokens for NPM, GitHub, and Codecov each with the
# appropriate permissions.
#
# Do a dry run first:
npm run release -- --skip-tasks manual --dry-run
# Then review CHANGELOG.md and, after making sure the next release includes the
# commits you're expecting, do the actual release:
npm run release -- --skip-tasks manual
Sometimes, for a variety of reasons, the maintenance window on a project may close for good. It happens. And when it does, there is a need to make clear to all current and future users that the project and its assets (repository, published packages, etc) are to be considered deprecated and that no further maintenance is intended.
With somber focus, the following steps should be taken:
Tip
If you're using symbiote, all of this can be done automatically:
npx symbiote project renovate --deprecate
These steps were inspired by Richard Litt's checklist.
Important
If the deprecated project is using symbiote/xpipeline, at least
one of the commits created as a result of following these instructions must be
of the build
type so that a final "deprecated" version with updated
deprecation documentation is released. If operating on a monorepo, said commit
must touch every deprecated package.
- Update Metadata.
GitHub repositories have metadata settings that can be configured via the gear icon. Once the modal is revealed, the following settings should be updated:
-
⛔️ [DEPRECATED]
should be prepended to the description. -
If the website is pointing to NPM, the input box should be emptied.
-
All three checkboxes under "Include in the home page" (i.e. "Releases," "Packages," and "Deployments) should be unchecked.
Be sure to save the changes by pressing "Save changes"!
- Update
README.md
.
The project root README.md
file and any README files at packages/*/README.md
(if applicable) should be updated as follows:
-
The level one heading at the top of the file should be updated to "# ⛔️ DEPRECATED/UNMAINTAINED" (no quotes).
-
All badges except badge-blm should be removed; badge-unmaintained should be added.
-
Under the updated level one heading, a caution alert should be included that details the reason why this project is being deprecated. Any alternatives, forks, see-also's, and/or future projects should be linked here.
What follows is an example outcome of the above steps:
<!-- badges-start -->
[![Black Lives Matter!][badge-blm]][link-blm]
[![!!UNMAINTAINED!!][badge-unmaintained]][link-unmaintained]
<!-- badges-end -->
# ⛔️ DEPRECATED/UNMAINTAINED
> [!CAUTION]
>
> This project has been superseded (and all of its useful bits subsumed) by
> [something-else](https://github.com/something/else).
...
[badge-blm]: https://xunn.at/badge-blm 'Join the movement!'
[link-blm]: https://xunn.at/donate-blm
[badge-unmaintained]:
https://xunn.at/badge-unmaintained
'Unfortunately, this project is unmaintained (forks welcome!)'
[link-unmaintained]: https://xunn.at/link-unmaintained
- Update
package.json
(if applicable).
If the project has a package.json
file at its root and/or at
packages/*/package.json
(if applicable), they should be updated as follows:
-
The
description
string should be prefixed with⛔️ [DEPRECATED]
. -
The strings
"deprecated", "obsolete", "archived"
should be added to thekeywords
array if this file defines a published package.
- Update
package.json
(if applicable).
- Publish Final Version.
Any updates to source repository assets (including package.json
files
and adding deprecation language to README.md
files) should be published as a
single patch release in a polyrepo, or one release per package in a monorepo.
- Issue Package-Wide Deprecation Command.
Use npm deprecate
to officially deprecate each package after their
final patch releases are published.
Consider moving the repository to a place where it is accessible but otherwise
out of the way, e.g. /repos/.deprecated/<deprecated-repo-here>
.
Thank you so much for helping to maintain this project!