Skip to content
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
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Published as `knit-cli` (the crates.io name `knit` is taken); the installed
# binary is still `knit`.
name = "knit-cli"
version = "0.1.0-alpha.42"
version = "0.1.0-alpha.43"
edition = "2021"
license = "Apache-2.0"
description = "A local-first CLI for coordinating cross-repo feature bundles."
Expand All @@ -26,7 +26,7 @@ members = [".", "crates/knit-runtime"]

[dependencies]
anyhow = "1"
knit-runtime = { version = "0.1.0-alpha.42", path = "crates/knit-runtime" }
knit-runtime = { version = "0.1.0-alpha.43", path = "crates/knit-runtime" }
chrono = { version = "0.4", features = ["serde"] }
clap = { version = "4.5", features = ["derive"] }
ctrlc = { version = "3.4", features = ["termination"] }
Expand Down
2 changes: 1 addition & 1 deletion crates/knit-runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# version-control shaped; the CLI compiles it in and adapts bundle state into
# the crate's RuntimeContext contract.
name = "knit-runtime"
version = "0.1.0-alpha.42"
version = "0.1.0-alpha.43"
edition = "2021"
license = "Apache-2.0"
description = "Per-bundle docker-compose runtime for knit cross-repo bundles."
Expand Down
10 changes: 10 additions & 0 deletions docs/release-0.1.0-alpha.43.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Knit 0.1.0-alpha.43

Reviews merged on the host count as done. Landing plans leave them out, and a
bundle whose reviews have all merged closes itself once its landing plan has
nothing left to run: the saved plan, or without one, the plan the project's
landing recipes would generate. `knit publish sync`, `knit land`, and
`knit publish sync --from-artifact` (with `--plan` or `--project-file`) apply
the rule, so a bundle another maintainer merged no longer waits for a landing
nobody can run. `knit land remove <step>` drops a step from the saved plan, and
pulling an archived bundle removes its clean worktrees.
8 changes: 8 additions & 0 deletions schemas/land-plan.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,14 @@
"default": true,
"description": "Whether landing this plan finishes the bundle."
},
"alreadyMerged": {
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true,
"description": "Repositories whose review the host had already merged when the plan was generated; they have no merge step."
},
"changedRepos": {
"type": "array",
"items": {
Expand Down
15 changes: 15 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1473,6 +1473,12 @@ pub enum PublishCommand {
/// Write the updated bundle JSON artifact to this path.
#[arg(long)]
out: Option<PathBuf>,
/// The bundle's saved landing plan. With every review merged, the bundle closes only when this plan has no step left besides merges.
#[arg(long, requires = "from_artifact")]
plan: Option<PathBuf>,
/// The bundle's project. Without a saved plan, the project's landing recipes decide whether steps besides merges are still due.
#[arg(long, requires = "from_artifact")]
project_file: Option<PathBuf>,
/// Sync every tracked repo instead of only repos with recorded work or publications.
#[arg(long)]
all: bool,
Expand Down Expand Up @@ -1574,6 +1580,15 @@ pub enum LandCommand {
#[arg(long)]
force: bool,
},
/// Take steps out of the saved plan, such as a deployment you do not want to run.
Remove {
/// Step ids to remove, as `knit land` lists them.
#[arg(required = true)]
steps: Vec<String>,
/// Plan file to edit; defaults to the bundle's plan for this destination.
#[arg(long)]
plan: Option<PathBuf>,
},
/// Validate an exact saved plan without executing it.
Validate {
#[arg(long)]
Expand Down
24 changes: 14 additions & 10 deletions src/commands/bundle/lifecycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,22 +80,26 @@ pub(crate) fn archive_active_bundle(
} else {
crate::commands::clean::clean_worktrees_for_bundle(active, force)?
};
let now = now_iso();
let node_id = crate::ids::node_id("archive");
active.bundle.state = Some(BundleState::Archived);
active.bundle.archived_at = Some(now.clone());
active
.bundle
.nodes
.push(BundleNode::feature_archived(node_id.clone(), now, reason));
active.bundle.head_node_id = active.bundle.nodes.last().map(|node| node.id.clone());
active.bundle.updated_at = now_iso();
let node_id = mark_archived(&mut active.bundle, reason);
Ok(ArchiveSummary {
node_id,
removed_worktrees,
})
}

pub(crate) fn mark_archived(bundle: &mut ChangeGroup, reason: Option<String>) -> String {
let now = now_iso();
let node_id = crate::ids::node_id("archive");
bundle.state = Some(BundleState::Archived);
bundle.archived_at = Some(now.clone());
bundle
.nodes
.push(BundleNode::feature_archived(node_id.clone(), now, reason));
bundle.head_node_id = bundle.nodes.last().map(|node| node.id.clone());
bundle.updated_at = now_iso();
node_id
}

pub(crate) fn clear_workspace_active_if_matches(root: &Path, bundle_id: &str) -> Result<()> {
clear_active_if_matches(root, bundle_id)
}
Expand Down
Loading
Loading