Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Allow running default workflows (those that would be created by--generate) with no knope.toml file. #286

Merged
merged 1 commit into from
Sep 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

A command line tool that happily completes the tasks which most developers find tedious.

## TL;DR
## What it does

Put a `knope.toml` in your project which defines some workflows, then run them with `knope`. Check out the file by the same name in this project for an example, or [read the docs](https://knope-dev.github.io/knope/) for more info.
If you're already using [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) and [semantic versioning](https://semver.org/), Knope can probably automate bumping versions and creating releases for you. Try running a `knope release --dry-run` to see what it would do for your current project with no config.

Knope can do much more with some customization, [read the docs](https://knope-dev.github.io/knope/) for more info.
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

- [Introduction](introduction.md)
- [Installation](installation.md)
- [Default Workflows](default_workflows.md)
- [knope.toml](config/config.md)
- [Workflows](config/workflow.md)
- [Steps](config/step/step.md)
Expand Down
28 changes: 28 additions & 0 deletions docs/src/default_workflows.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Default Workflows

Knope can do a lot out of the box, with no need for a [config file](config/config.md). If no file is found, Knope will use the same config as it would create with `knope --generate`.

```admonish warning
If you have a `knope.toml` file in your project, this page is no longer relevant to you, as default workflows are only used when _no_ config file is found.
```

## `release`

Without any config, you can run `knope release` to create a new release from [conventional commits]. This will:

1. Update the version in any [supported package files](config/packages.md#versioned_files) based on the [semantic version] determined from all commits since the last release. For more detail, see the [`PrepareRelease`] step.
2. Update a `CHANGELOG.md` file (if any) with the body of relevant commits (again, see the [`PrepareRelease`] step for more detail).
3. Commit the changes to the versioned and changelog files and push that commit.
4. Create a release which is one of the following, see the [`Release`] step for more detail:
1. If your remote is GitHub, create a new release on GitHub with the same body as the changelog entry. **This requires a `GITHUB_TOKEN` environment variable to be set.**
2. If the remote is not GitHub, a tag will be created and pushed to the remote.

### Additional Options

1. `--dry-run` will run the workflow without modifying any files or interacting with the remote. Instead, all the steps that _would_ happen will be printed to the screen so you can verify what will happen.
2. `--prerelease-label` will tell `knope` to create a prerelease with a given label. For example, `knope release --prerelease-label rc` will create a release with the _next_ calculated version (as if you had run `knope release`), but with the `-rc.0` suffix (or `rc.1`, `rc.2`, etc. if you have already created a release with that label).

[conventional commits]: https://www.conventionalcommits.org/en/v1.0.0/
[semantic version]: https://semver.org
[`PrepareRelease`]: config/step/PrepareRelease.md
[`Release`]: config/step/Release.md
6 changes: 5 additions & 1 deletion docs/src/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ Knope is a CLI/CI tool which automates common tasks for developers. Things like

## How it Works

You create a file called `knope.toml` in your project directory which defines some workflows. The format of this file is described in [the chapter on config][config], the key piece to which is the `workflows` array. For a full example of a `knope.toml`, check out the file for this project! You can get started quickly with `knope --generate` which will give you some starter workflows.
```admonish info
For some use-cases, you don't need to create a `knope.toml` file! If no file is detected, Knope will use the same config at runtime that it would create with `knope --generate`. Run `knope --generate` to see what you get for free, or check out the [default workflows](default_workflows.md).
```

You create a file called `knope.toml` in your project directory which defines some workflows. The format of this file is described in [the chapter on config][config], the key piece to which is the `workflows` array. You can get started quickly with `knope --generate` which will give you some starter workflows.

Once you've got a config set up, you just run this program (`knope` if you installed normally via cargo). That will prompt you to select one of your configured workflows. Do that and you're off to the races!

Expand Down
53 changes: 0 additions & 53 deletions knope.toml

This file was deleted.

28 changes: 12 additions & 16 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,17 @@ pub(crate) struct Config {
impl Config {
const CONFIG_PATH: &'static str = "knope.toml";

/// Create a Config from a TOML file.
/// Create a Config from a TOML file or load the default config via `generate`
///
/// ## Errors
/// 1. Provided path is not found
/// 2. Cannot parse file contents into a Config
/// 1. Cannot parse file contents into a Config
pub(crate) fn load() -> Result<Self> {
let contents = fs::read_to_string(Self::CONFIG_PATH)
.into_diagnostic()
.wrap_err_with(|| {
format!(
"Could not find {CONFIG_PATH}",
CONFIG_PATH = Self::CONFIG_PATH
)
})?;
let contents = if let Ok(contents) = fs::read_to_string(Self::CONFIG_PATH) {
contents
} else {
log::debug!("No `knope.toml` found, using default config");
return Ok(generate());
};
toml::from_str(&contents)
.into_diagnostic()
.wrap_err("Invalid TOML when parsing config")
Expand Down Expand Up @@ -125,8 +122,8 @@ pub(crate) struct Package {
pub(crate) scopes: Option<Vec<String>>,
}

/// Generate a brand new config file for the project in the current directory.
pub(crate) fn generate() -> Result<()> {
/// Generate a brand new Config for the project in the current directory.
pub(crate) fn generate() -> Config {
let variables = hash_map! {
String::from("$version"): command::Variable::Version,
};
Expand Down Expand Up @@ -167,7 +164,7 @@ pub(crate) fn generate() -> Result<()> {
],
};

let config = Config {
Config {
workflows: vec![Workflow {
name: String::from("release"),
steps: vec![
Expand All @@ -181,8 +178,7 @@ pub(crate) fn generate() -> Result<()> {
github,
package: find_packages(),
packages: None,
};
config.write_out()
}
}

/// Config required for steps that interact with Jira.
Expand Down
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ mod workflow;
pub fn run(cli: Cli) -> Result<()> {
if cli.generate {
println!("Generating a knope.toml file");
return config::generate();
let config = config::generate();
return config.write_out();
}

let preselected_workflow = cli.workflow;
Expand Down
103 changes: 103 additions & 0 deletions tests/no_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//! Test the default workflows that should work when no `knope.toml` exists.

use std::fs::copy;
use std::path::Path;

use rstest::rstest;
use snapbox::cmd::{cargo_bin, Command};

use git_repo_helpers::*;

mod git_repo_helpers;

/// Run `knope release --dry-run` on a repo with no remote.
#[test]
fn release_no_remote() {
// Arrange
let temp_dir = tempfile::tempdir().unwrap();
let temp_path = temp_dir.path();
let source_path = Path::new("tests/no_config/no_remote");
setup_commits(temp_path);
copy(source_path.join("Cargo.toml"), temp_path.join("Cargo.toml")).unwrap();

// Act
let assert = Command::new(cargo_bin!("knope"))
.arg("release")
.arg("--dry-run")
.current_dir(temp_path)
.assert();

// Assert
assert
.success()
.stdout_eq_path(source_path.join("stdout.txt"));
}

/// Run `knope release --dry-run` on a repo with supported metadata files.
#[rstest]
#[case(&["Cargo.toml"], "Cargo")]
#[case(&["pyproject.toml"], "pyproject")]
#[case(&["package.json"], "package")]
#[case(&["go.mod"], "go")]
#[case(&["Cargo.toml", "pyproject.toml", "package.json"], "multiple")]
fn test_packages(#[case] source_files: &[&str], #[case] case: &str) {
// Arrange
let temp_dir = tempfile::tempdir().unwrap();
let temp_path = temp_dir.path();
let source_path = Path::new("tests/no_config/packages");
setup_commits(temp_path);

for source_file in source_files {
copy(source_path.join(source_file), temp_path.join(source_file)).unwrap();
}
copy(
source_path.join("CHANGELOG.md"),
temp_path.join("CHANGELOG.md"),
)
.unwrap();

// Act
let assert = Command::new(cargo_bin!("knope"))
.arg("release")
.arg("--dry-run")
.current_dir(temp_path)
.assert();

// Assert
assert
.success()
.stdout_eq_path(source_path.join(format!("{case}_stdout.txt")));
}

/// Run `knope release --dry-run` on a repo with a GitHub remote to test that integration.
#[rstest]
#[case::ssh("[email protected]:knope-dev/knope.git")]
#[case::https("https://github.com/knope-dev/knope.git")]
fn generate_github(#[case] remote: &str) {
// Arrange
let temp_dir = tempfile::tempdir().unwrap();
let temp_path = temp_dir.path();
let source_path = Path::new("tests/no_config/github");
setup_commits(temp_path);
add_remote(temp_path, remote);
copy(source_path.join("Cargo.toml"), temp_path.join("Cargo.toml")).unwrap();

// Act
let assert = Command::new(cargo_bin!("knope"))
.arg("release")
.arg("--dry-run")
.current_dir(temp_path)
.assert();

// Assert
assert
.success()
.stdout_eq_path(source_path.join("stdout.txt"));
}

fn setup_commits(path: &Path) {
init(path);
commit(path, "feat: Existing Feature");
tag(path, "v1.0.0");
commit(path, "feat!: Breaking Change");
}
2 changes: 2 additions & 0 deletions tests/no_config/github/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[package]
version = "1.0.0"
19 changes: 19 additions & 0 deletions tests/no_config/github/knope.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[[workflows]]
name = "release"

[[workflows.steps]]
type = "PrepareRelease"

[[workflows.steps]]
type = "Command"
command = "git commit -m \"chore: prepare release $version\" && git push"

[workflows.steps.variables]
"$version" = "Version"

[[workflows.steps]]
type = "Release"

[github]
owner = "knope-dev"
repo = "knope"
9 changes: 9 additions & 0 deletions tests/no_config/github/stdout.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Would bump package version to 2.0.0
Would run git commit -m "chore: prepare release 2.0.0" && git push
Would create a release on GitHub with name and tag v2.0.0 and body:
## 2.0.0

### Breaking Changes

- Breaking Change

2 changes: 2 additions & 0 deletions tests/no_config/no_remote/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[package]
version = "1.0.0"
4 changes: 4 additions & 0 deletions tests/no_config/no_remote/stdout.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Would bump package version to 2.0.0
Would run git commit -m "chore: prepare release 2.0.0"
Would create Git tag v2.0.0
Would run git push && git push --tags
5 changes: 5 additions & 0 deletions tests/no_config/packages/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## 1.0.0

### Features

- Existing feature
2 changes: 2 additions & 0 deletions tests/no_config/packages/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[package]
version = "1.0.0"
11 changes: 11 additions & 0 deletions tests/no_config/packages/Cargo_stdout.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Would bump package version to 2.0.0
Would add the following to CHANGELOG.md:
## 2.0.0

### Breaking Changes

- Breaking Change

Would run git commit -m "chore: prepare release 2.0.0"
Would create Git tag v2.0.0
Would run git push && git push --tags
12 changes: 12 additions & 0 deletions tests/no_config/packages/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module github.com/knope-dev/knope

go 1.19

require (
example.com/othermodule v1.2.3
example.com/thismodule v1.2.3
example.com/thatmodule v1.2.3
)

replace example.com/thatmodule => ../thatmodule
exclude example.com/thismodule v1.3.0
11 changes: 11 additions & 0 deletions tests/no_config/packages/go_stdout.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Would bump package version to 2.0.0
Would add the following to CHANGELOG.md:
## 2.0.0

### Breaking Changes

- Breaking Change

Would run git commit -m "chore: prepare release 2.0.0"
Would create Git tag v2.0.0
Would run git push && git push --tags
11 changes: 11 additions & 0 deletions tests/no_config/packages/multiple_stdout.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Would bump package version to 2.0.0
Would add the following to CHANGELOG.md:
## 2.0.0

### Breaking Changes

- Breaking Change

Would run git commit -m "chore: prepare release 2.0.0"
Would create Git tag v2.0.0
Would run git push && git push --tags
3 changes: 3 additions & 0 deletions tests/no_config/packages/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"version": "1.0.0"
}
Loading