diff --git a/README.md b/README.md index 7e5be91..f83728e 100644 --- a/README.md +++ b/README.md @@ -1,451 +1,9 @@ # git-next -- Status: **BETA** - dog-fooding +## Trunk-based developement manager. `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 - -- Allows enforce the requirement for each commit to pass the CI pipeline before being - included in the main branch -- Provides a server component that manages the trunk-based development process -- Ensure a consistent, high-quality codebase by preventing untested changes - from being added to main - -See [Behaviour](#behaviour) to learn how we do this. - -## 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` from : - -```shell -cargo install git-next -``` - -If you use [mise](https://mise.jdx.dev): - -```shell -mise use -g cargo:git-next -``` - -Or you can install `git-next` from source after cloning: - -```shell -cargo install --path crates/cli -``` - -## Roadmap - -- [x] cli -- [x] server -- [ ] notifications - notify user when intervention required (e.g. to rebase) -- [ ] tui overview -- [ ] webui overview - -## 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` and `dev` 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 is `pushed`. -- The `dev` branch _must_ have the `main` branch as an ancestor. -- The `next` branch _must_ have the `main` 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. - -```toml -[forge.github] -forge_type = "GitHub" -hostname = "github.com" -user = "username" -token = "api-key" -``` - -- **forge_type** - one of: `ForgeJo` or `GitHub` -- **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. - -```toml -[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: - -```toml -[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 - -The branch names are configurable, but we will talk about `main`, `next` and `dev`. - -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) - -```mermaid -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. - -```mermaid -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. - -```mermaid -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. - -```mermaid -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: - -```shell -git next init -``` - -This will create a `.git-next.toml` file. [Default](./crates/cli/default.toml) - -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: - -```shell -git next server init -``` - -This will create a `git-next-server.toml` file. [Default](./crates/server/server-default.toml) - -Edit this file to your needs. See the [Configuration](#configuration) section above. - -### Run the server - -In the directory with your `git-next-server.toml` file, run the command: - -```shell -git next server start -``` - -### Forges - -The following forges are supported: - -- [ForgeJo](https://forgejo.org) (probably compatible with Gitea, but not tested) -- [GitHub](https://github.com/) - -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: - -```toml -[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: - -```toml -[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](https://github.com/settings/tokens/new) 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](https://git.kemitix.net/kemitix/git-next/issues/new). -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](https://just.systems/man/en/chapter_3.html)) - -## Crate Dependency - -The following diagram shows the dependency between the crates that make up `git-next`: - -```mermaid -stateDiagram-v2 - - cli --> server - - file_watcher_actor --> config - file_watcher_actor --> actor_macros - - forge --> config - forge --> git - forge --> forge_forgejo - forge --> forge_github - - forge_forgejo --> config - forge_forgejo --> git - - forge_github --> config - forge_github --> git - - git --> config - - repo_actor --> config - repo_actor --> git - repo_actor --> forge - repo_actor --> actor_macros - - server --> config - server --> file_watcher_actor - server --> server_actor - - server_actor --> config - server_actor --> git - server_actor --> forge - server_actor --> repo_actor - server_actor --> actor_macros - server_actor --> file_watcher_actor - server_actor --> webhook_actor - - webhook_actor --> config - webhook_actor --> repo_actor -``` - -## License - -`git-next` is released under the [MIT License](./LICENSE). +See [README.md](/crates/cli/README.md) for more information. diff --git a/crates/cli/README.md b/crates/cli/README.md new file mode 100644 index 0000000..598d75f --- /dev/null +++ b/crates/cli/README.md @@ -0,0 +1,459 @@ +# git-next + +## Trunk-based developement manager. + +> A source-control branching model, where developers collaborate on code in a single branch +> called ‘trunk’, resist any pressure to create other long-lived development branches by +> employing documented techniques. They therefore avoid merge hell, do not break the build, +> and live happily ever after. - [source](https://trunkbaseddevelopment.com) + +- Status: **BETA** - 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 + +- Allows enforcing the requirement for each commit to pass the CI pipeline before being + included in the main branch +- Provides a server component that manages the trunk-based development process +- Ensure a consistent, high-quality codebase by preventing untested changes + from being added to main +- Requires each commit uses conventional commit format. + +See [Behaviour](#behaviour) to learn how we do this. + +## 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` from : + +```shell +cargo install git-next +``` + +If you use [mise](https://mise.jdx.dev): + +```shell +mise use -g cargo:git-next +``` + +Or you can install `git-next` from source after cloning: + +```shell +cargo install --path crates/cli +``` + +## Roadmap + +- [x] cli +- [x] server +- [ ] notifications - notify user when intervention required (e.g. to rebase) +- [ ] tui overview +- [ ] webui overview + +## 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` and `dev` 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 is `pushed`. +- The `dev` branch _must_ have the `main` branch as an ancestor. +- The `next` branch _must_ have the `main` 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. + +```toml +[forge.github] +forge_type = "GitHub" +hostname = "github.com" +user = "username" +token = "api-key" +``` + +- **forge_type** - one of: `ForgeJo` or `GitHub` +- **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. + +```toml +[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: + +```toml +[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 + +The branch names are configurable, but we will talk about `main`, `next` and `dev`. + +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) + +```mermaid +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. + +```mermaid +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. + +```mermaid +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. + +```mermaid +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: + +```shell +git next init +``` + +This will create a `.git-next.toml` file. [Default](./crates/cli/default.toml) + +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: + +```shell +git next server init +``` + +This will create a `git-next-server.toml` file. [Default](./crates/server/server-default.toml) + +Edit this file to your needs. See the [Configuration](#configuration) section above. + +### Run the server + +In the directory with your `git-next-server.toml` file, run the command: + +```shell +git next server start +``` + +### Forges + +The following forges are supported: + +- [ForgeJo](https://forgejo.org) (probably compatible with Gitea, but not tested) +- [GitHub](https://github.com/) + +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: + +```toml +[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: + +```toml +[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](https://github.com/settings/tokens/new) 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](https://git.kemitix.net/kemitix/git-next/issues/new). +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](https://just.systems/man/en/chapter_3.html)) + +## Crate Dependency + +The following diagram shows the dependency between the crates that make up `git-next`: + +```mermaid +stateDiagram-v2 + + cli --> server + + file_watcher_actor --> config + file_watcher_actor --> actor_macros + + forge --> config + forge --> git + forge --> forge_forgejo + forge --> forge_github + + forge_forgejo --> config + forge_forgejo --> git + + forge_github --> config + forge_github --> git + + git --> config + + repo_actor --> config + repo_actor --> git + repo_actor --> forge + repo_actor --> actor_macros + + server --> config + server --> file_watcher_actor + server --> server_actor + + server_actor --> config + server_actor --> git + server_actor --> forge + server_actor --> repo_actor + server_actor --> actor_macros + server_actor --> file_watcher_actor + server_actor --> webhook_actor + + webhook_actor --> config + webhook_actor --> repo_actor +``` + +## License + +`git-next` is released under the [MIT License](./LICENSE).