Paul Campbell
1010eaec64
All checks were successful
Rust / build (push) Successful in 1m5s
ci/woodpecker/push/push-next Pipeline was successful
ci/woodpecker/push/cron-docker-builder Pipeline was successful
ci/woodpecker/push/tag-created Pipeline was successful
ci/woodpecker/cron/cron-docker-builder Pipeline was successful
ci/woodpecker/cron/push-next Pipeline was successful
ci/woodpecker/cron/tag-created Pipeline was successful
|
||
---|---|---|
.cargo | ||
.forgejo/workflows | ||
.git-hooks | ||
.woodpecker | ||
crates | ||
.git-next.toml | ||
.gitignore | ||
.rgignore | ||
bacon.toml | ||
Cargo.toml | ||
CHANGELOG.md | ||
cliff.toml | ||
default.toml | ||
Dockerfile | ||
Dockerfile.builder | ||
justfile | ||
LICENSE | ||
README.md | ||
renovate.json | ||
server-default.toml |
git-next
- Status: Alpha - dog-fooding
git-next
is a combined server and command-line tool that enables trunk-based
development workflows where each commit must pass CI before being included in
the main branch.
Features
- Enforce the requirement for each commit to pass the CI pipeline before being included in the main branch
- Provide a server component that manages the trunk-based development process
- Ensure a consistent, high-quality codebase by preventing untested changes from being merged
Prerequisits
- Rust 1.76.0 or later - https://www.rust-lang.org
- pgk-config
- libssl-dev
x86_64-unknown-linux-gnu
Additionally for this platform, to improved compilation times:
- clang-16
- mold
See .cargo/config.toml
for how they are configured.
Installation
You can install git-next
using Cargo:
cargo install --path .
Not yet available to install from crates.io
.
Branch Names
git-next
uses three branches, main
, next
and dev
, although they do not
need to have those names. In the documentation we will use those names, but
each repo must specify the names of the branches to use for each, even if they
happen to have those same names.
Configuration
- The branches to use for
main
,next
anddev
must be specified in either the.git-next.toml
in the repo itself, or in the server configuration file,git-next-server.toml
. See below for details. - CI checks should be configured to run when the
next
branch ispushed
. - The
dev
branch must have themain
branch as an ancestor. - The
next
branch must have themain
branch as an ancestor.
Server
The server is configured by the git-next-server.toml
file.
http
The server needs to be able to receive webhook notifications from your forge, (e.g. github.com). You can do this via any method that suits your environment, e.g. ngrok or a reverse proxy from a web server that itself can route traffic to the machine you are running the git-next server on.
Specify the address and port the server should listen to for incoming webhooks. This is the address and port that your reverse proxy should route traffic to.
- addr - the IP address the server should bind to
- port - the IP port the server should bind to
webhook
Your forges need to know where they should route webhooks to. This should be an address this is accessible to the forge. So, for github.com, it would need to be a publicly accessible HTTPS URL. For a self-hosted forge, e.g. ForgeJo, on your own network, then it only needs to be accessible from the server your forge is running on.
- url - the HTTPS URL for forges to send webhook to
storage
git-next
will create a bare clone of each repo that you configure it to
monitor. They will all be created in the directory specified here. This data
does not need to be backed up, as any missing information will be cloned when
the server starts up.
- path - directory to store local copies of monitored repos
forge
Within the forge tree, specify each forge you want to monitor repos on.
Give your forge an alias, e.g. default
, gh
, github
.
e.g.
[forge.github]
forge_type = "GitHub"
hostname = "github.com"
user = "username"
token = "api-key"
- forge_type - one of:
ForgeJo
orGitHub
- hostname - the hostname for the forge.
- user - the user to authenticate as
- token - application token for the user. See below for the permissions required for on each forge.
Generally, the user
will need to be able to push to main
and to force-push
to next
.
repos
For each forge, you need to specify which repos on the forge you want to
monitor. They do not need to be owned by the user
, but they user
must have
the push
and force-push
permissions as mentioned above for each of the
repositories.
e.g.
[forge.github.repos]
my-repo = { repo = "owner/repo", branch = "main", gitdir = "/home/pcampbell/project/my-repo" }
[forge.github.repos.other-repo]
repo = "user/other"
branch = "master"
main = "master"
next = "ci-testing"
dev = "trunk"
Note that toml allows specifying the values on one line, or across multiple
lines. Both are equivalent. What is not equivalent between my-repo
and
other-repo
, is that one will require a configuration file within the repo
itself. other-repo
specifies the main
, next
and dev
branches to be
used, but my-repo
doesn't.
A sample .git-next-toml
file that would need to exist in my-repo
's owner/repo
repo, on the main
branch:
[branches]
main = "main"
next = "next"
dev = "dev"
- repo - the owner and name of the repo to be monitored
- branch - the branch to look for a
.git-next.toml
file if needed - gitdir - (optional) you can use a local copy of the repo
- main - the branch to use as
main
- next - the branch to use as
next
- dev - the branch to use as
dev
gitdir
Additional notes on using gitdir
:
When you specify the gitdir
value, the repo cloned in that directory will
be used for perform the equivalent of git fetch
, git push
and git push --force-with-lease
.
These commands will not affect the contents of your working tree, nor will it change any local branches. Only the details about branches on the remote forge will be updated.
Currently git-next
can only use a gitdir
if the forge and repo is the
same one specified as the origin
remote. Otherwise the behaviour is
untested and undefined.
Behaviour
Development happens on the dev
branch, where each commit is expected to
be able to pass the CI checks.
(Note: in the diagrams, mermaid isn't capable of showing main
and next
on
the same commit, so we show next
as empty)
gitGraph
commit
commit
branch next
branch dev
commit
commit
commit
When the git-next
server sees that the dev
branch is ahead of the next
branch, it will push the next
branch fast-forward one commit along the dev
branch.
gitGraph
commit
commit
branch next
commit
branch dev
commit
commit
It will then wait for the CI checks to pass for the newly updated next
branch.
When the CI checks for the next
branch pass, it will push the main
branch
fast-forward to the next
branch. We return to the top and start again.
gitGraph
commit
commit
commit
branch next
branch dev
commit
commit
If the CI checks should fail for the next
branch, the developer should
amend that commit in the history of their dev
branch.
They should then force-push their rebased dev
branch.
gitGraph
commit
commit
branch next
commit
checkout main
branch dev
commit
commit
commit
git-next
will then detect that the next
branch is no longer part of the
dev
branch ancestory, and will reset next
back to main
.
We then return to the top, where git-next
sees that dev
is ahead of next
.
When the dev
branch is on the same commit as the main
branch, then there
are no pending commits and git-next
will wait until it receives a webhook
indicating that there has been a push to one of the branches. At which point
it will start at the top again.
Important
The dev
branch should have the next
branch as an ancestor.
However, when the commit on tip of the next
branch has failed CI and is
amended, this will not be the case. When this happens git-next
will
force-push the next
branch back to the same commit as the main
branch.
This is the only time a force-push will happen in git-next
.
In short, the next
branch belongs to git-next
. Don't try to update it
yourself. git-next
will update the next
it as it sees fit.
Getting Started
To use git-next
for trunk-based development, follow these steps:
Initialise the repo (optional)
You need to specify which branches you are using. You can do this in the repo, or in the server configuration.
To create a default config file for the repo, run this command in the root of your repo:
git next init
This will create a .git-next.toml
file. Default
By default the expected branches are main
, next
and dev
. Each of these
three branches must exist in your repo.
Initialise the server
The server uses the file git-next-server.toml
for configuration. It expects
to find this file the the current directory when executed.
The create the default config file, run this command:
git next server init
This will create a git-next-server.toml
file. Default
Edit this file to your needs. See the Configuration section above.
Run the server
In the directory with your git-next-server.toml
file, run the command:
git next server start
Forges
The following forges are supported:
Note: ForgeJo is a hard fork of Gitea, but currently they are largely compatible.
For now using a forge_type
of ForgeJo
with a Gitea instance will probably work
okay. The only API calls we make are around registering and unregistering webhooks.
So, as long as those APIs remain the same, they should be compatible.
ForgeJo
Configure the forge in git-next-server.toml
like:
[forge.jo]
forge_type = "ForgeJo"
hostname = "git.myforgejo.com"
user = "bob"
token = "..."
[forge.jo.repos]
hello = { repo = "user/hello", branch = "main", gitdir = "/opt/git/projects/user/hello.git" } # maps to https://git.example.net/user/hello on the branch 'main'
world = { repo = "user/world", branch = "master", main = "master", next = "upcoming", "dev" = "develop" } # maps to the 'master' branch
The token is created on your ForgeJo instance at (for example)
https://git.myforgejo.com/user/settings/applications
and requires the write:repository
permission.
GitHub
Configure the forge in git-next-server.toml
like:
[forge.gh]
forge_type = "GitHub"
hostname = "github.com" # required even for GitHub
user = "bob"
token = "..."
[forge.gh.repos]
hello = { repo = "user/hello", branch = "main", gitdir = "/opt/git/projects/user/hello.git" } # maps to https://github.com/user/hello on the branch 'main'
world = { repo = "user/world", branch = "master", main = "master", next = "upcoming", "dev" = "develop" } # maps to the 'master' branch
The token is created here and requires the repo
and admin:repo_hook
permissions.
Contributing
Contributions to git-next
are welcome! If you find a bug or have a feature
request, please
create an issue.
If you'd like to contribute code, feel free to submit changes.
Before you start committing, run the just install-hooks
command to setup the
Git Hooks. (Get Just)
Crate Dependency
The following diagram shows the dependency between the crates that make up git-next
:
stateDiagram-v2
cli --> server
cli --> git
server --> config
server --> git
server --> forge
server --> repo_actor
git --> config
forge --> config
forge --> git
forge --> forgejo
forge --> github
forgejo --> config
forgejo --> git
github --> config
github --> git
repo_actor --> config
repo_actor --> git
repo_actor --> forge
License
git-next
is released under the MIT License.