Notes on maintaining the Neovim project.
- Decide by cost-benefit
- Write down what was decided
- Constraints are good
- Use automation to solve problems
- Never break the API... but sometimes break the UI
In practice we haven't found a way to forecast more precisely than "next" and "after next". So there are usually one or two (at most) planned milestones:
- Next bugfix-release (1.0.x)
- Next feature-release (1.x.0)
The forecasting problem might be solved with an explicit priority system (like Bram's todo.txt). Meanwhile the Neovim priority system is defined by:
- PRs nearing completion.
- Issue labels. E.g. the
has:plan
label increases the ticket's priority merely for having a plan written down: it is closer to completion than tickets without a plan. - Comment activity or new information.
Anything that isn't in the next milestone, and doesn't have a finished PR—is just not something you care very much about, by construction. Post-release you can review open issues, but chances are your next milestone is already getting full... :)
Release "often", but not "early".
The (unreleased) master
branch is the "early" channel; it should not be
released if it's not stable. High-risk changes may be merged to master
if
the next release is not imminent.
For maintenance releases, create a release-x.y
branch. If the current release
has a major bug:
- Fix the bug on
master
. - Cherry-pick the fix to
release-x.y
. - Cut a release from
release-x.y
.- Run
./scripts/release.sh
- Update (force-push) the remote
stable
tag. - The CI job
will update the release assets and force-push to the
stable
tag.
- Run
Neovim automation includes a backport bot.
Trigger the action by labeling a PR with backport release-X.Y
. See .github/workflows/backport.yml
.
Neovim inherits many features and design decisions from Vim, not all of which align with the goals of this project. It is sometimes desired or necessary to remove existing features, or refactor parts of the code that would change user's workflow. In these cases, a deprecation policy is needed to properly inform users of the change.
When a (non-experimental) feature is slated to be removed it should:
- Be soft deprecated in the next release
- Use of the deprecated feature will still work.
- This means deprecating via documentation and annotation (
@deprecated
) only. - Include a note in
news.txt
underDEPRECATIONS
.
- Be hard deprecated in a following a release in which it was soft deprecated.
- Use of the deprecated feature will still work but should issue a warning
(typically via
vim.deprecate()
for Lua features). - Features implemented in Vimscript or in C will need bespoke implementations to communicate to users that the feature is deprecated
- Be removed in a release following the release in which it was hard deprecated
- Usually this will be the next release, but it may be a later release if a longer deprecation cycle is desired
- If possible, keep the feature as a stub (e.g. function API) and issue an error when it is accessed.
Example:
Deprecation Removal
┆ ┆ ┆
┆ Soft ┆ Hard ┆
┆ Deprecation ┆ Deprecation ┆
┆ Period ┆ Period ┆
────────────────────────────────────────────────────────────
Version: 0.10 0.11 0.12
────────────────────────────────────────────────────────────
Old code Old code Old code
+ +
New code New code New code
Feature removals which may benefit from community input or further discussion should also have a tracking issue (which should be linked to in the release notes).
Exceptions to this policy may be made (for experimental subsystems or when there is broad consensus among maintainers). The rationale for the exception should be stated explicitly and publicly.
These "bundled" dependencies can be updated by bumping their versions in cmake.deps/deps.txt
.
Some can be auto-bumped by scripts/bump_deps.lua
.
- LuaJIT
- Lua
- Luv
- When bumping, also sync our bundled documentation with the upstream documentation.
- gettext
- libiconv
- libuv
- libvterm
- lua-compat
- tree-sitter
- unibilium
- treesitter parsers
These dependencies are "vendored" (inlined), we must update the sources manually:
src/mpack/
: libmpack- send improvements upstream!
src/xdiff/
: xdiffsrc/cjson/
: lua-cjsonsrc/klib/
: Klibruntime/lua/vim/inspect.lua
: inspect.luasrc/nvim/tui/terminfo_defs.h
: terminfo definitions- Run
scripts/update_terminfo.sh
to update these definitions.
- Run
runtime/lua/vim/lsp/_meta/protocol.lua
: LSP specification- Run
scripts/gen_lsp.lua
to update.
- Run
runtime/lua/vim/_meta/lpeg.lua
: LPeg definitions.- Refer to
LuaCATS/lpeg
for updates.
- Refer to
runtime/lua/vim/re.lua
: LPeg regex module.- Vendored from LPeg. Needs to be updated when LPeg is updated.
src/bit.c
: only for PUC lua: port ofrequire'bit'
from luajit https://bitop.luajit.org/runtime/lua/coxpcall.lua
: coxpcall (only needed for PUC lua, builtin to luajit)src/termkey
: libtermkey
We may maintain forks, if we are waiting on upstream changes: https://github.com/neovim/neovim/wiki/Deps
- GitHub users:
- Domain names (held in https://namecheap.com):
- neovim.org
- neovim.io
- packspec.org
- pkgjson.org
- DNS for the above domains is managed in https://cloudflare.com (not the domain registrar)
Discussions from issues and PRs are backed up here: https://github.com/neovim/neovim-backup
-
CI and automation jobs are primarily driven by GitHub Actions.
-
Avoid macOS if an Ubuntu or a Windows runner can be used instead. This is because macOS runners have tighter restrictions on the number of concurrent jobs.
-
Runner versions:
- For special-purpose jobs where the runner version doesn't really matter,
prefer
-latest
tags so we don't need to manually bump the versions. An example of a special-purpose workflow islabeler.yml
. - For our testing jobs, which are in
test.yml
andbuild.yml
, prefer to use the latest stable (i.e. non-beta) version explicitly. Avoid using the-latest
tags here as it makes it difficult to determine from an unrelated PR if a failure is due to the PR itself or due to GitHub bumping the-latest
tag without our knowledge. There's also a high risk that automatically bumping the CI versions will fail due to manual work being required from experience. - For our release job, which is
release.yml
, prefer to use the oldest stable (i.e. non-deprecated) versions available. The reason is that we're trying to produce images that work in the broadest number of environments, and therefore want to use older releases.
- For special-purpose jobs where the runner version doesn't really matter,
prefer