Thank you for taking your time to contribute to Cocogitto! Below is a non-exhaustive list of what you can do to help Cocogitto.
If you spot a bug or want to request a feature you are welcome to open an issue.
The official Cocogitto documentation is hosted on the cocogitto/website repository. If you find something is missing or unclear please open a pull request or an issue there.
Before submitting a PR don't hesitate to talk about your feature request or bug fix either on the issue board or on our discord server. If you need an early review or guidance on how to implement a feature or bug fix, draft PRs are welcome.
Cocogitto is a toolset for Conventional Commits and SemVer , and we aim to follow these specifications.
In addition, our CI pipeline uses the following formatter and linter:
-
rustfmt is a code formatter for rust, refer to their documentation for installation.
Before committing your changes please run
cargo fmt --all
-
clippy is a code linter for rust, refer to their documentation for installation.
Use
cargo clippy
instead ofcargo build
to spot lints before committing your changes. -
git-hooks Cocogitto provides sharable git-hooks, if you want to save the hassle of manually running lints and formatters before each commit you can simply run
cog install-hook --all
.
unwrap()
usage should be avoided, if needed useexpect("why")
instead.- For convenience, errors in the cog CLI and the public API are wrapped with the
anyhow!
macro. On the other hand, in order to be predictable, every error in the private part of the crate should be defined in the correspondingerror.rs
file. For instance, git2 errors are defined under src/git/error.rs.
Before submitting a PR please make sure your code is tested. The CI pipeline ensures that coverage never drops by more than 1%, and total coverage should never go below 80%.
Testing git repositories:
Due to the extensive usage of git2 in Cocogitto, testing withing a repository is often required.
This kind of tests must use the #[sealed_test]
macro in place off the #[test]
macro. sealed_test allow to run a test
within a dedicated environment (a temporary working directory, and its own environment variables).
If writing an integration test you can set up a git repository with the tests/helpers.rs.
If you need to run some additional shell command or are not writing an integration test use the run_cmd!
/run_fun!
macros.
Unit test:
Cocogitto tests are organized as described in The Rust Programing Language book. Private function should be tested right where they live
Example:
// mod commit ...
#[cfg(test)]
mod test {
use crate::git::repository::Repository;
use anyhow::Result;
use cmd_lib::run_cmd;
use sealed_test::prelude::*;
use speculoos::prelude::*;
#[sealed_test]
fn create_commit_ok() -> Result<()> {
// Arrange
let repo = git_init_no_gpg()?;
run_cmd!(
echo changes > file;
git add .;
)?;
// Act
let oid = repo.commit("feat: a test commit");
// Assert
assert_that!(oid).is_ok();
Ok(())
}
// ...
}
Integration test:
These tests live in the tests directory.
- tests/lib_tests contains tests for the public API function
- tests/cog_tests contains CLI integration tests using the asserd_cmd crate
Example:
#[sealed_test]
fn should_skip_initialization_if_repository_exists() -> Result<()> {
// Arrange
git_init()?;
git_commit("The first commit")?;
// Act
cocogitto::init(".")?;
// Assert
assert_that!(Path::new("cog.toml")).exists();
assert_that!(git_log_head()?).is_equal_to("The first commit\n".to_string());
assert_that!(git_status()?).contains("new file: cog.toml");
Ok(())
}