Skip to content

feat: init product command for patchable #1112

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

Merged
merged 6 commits into from
May 15, 2025
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
14 changes: 7 additions & 7 deletions rust/patchable/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,21 @@ The version-level config contains:

### Template

If you're adding a completely new product, you need to create the product-level config once:
If you're adding a completely new product, you need to initialize the product-level config once using patchable:

```toml
# docker-images/druid/stackable/patches/patchable.toml
upstream = "https://github.com/apache/druid.git"
mirror = "https://github.com/stackabletech/druid.git"
```sh
cargo patchable init product druid --upstream https://github.com/apache/druid.git --default-mirror https://github.com/stackabletech/druid.git
```

This will create the product-level configuration in `docker-images/druid/stackable/patches/patchable.toml`.

If you just want to add a new version, initialize the version-level config with patchable:

```sh
cargo patchable init druid 28.0.0 --base=druid-28.0.0 --mirror
cargo patchable init version druid 28.0.0 --base druid-28.0.0 --mirror
```

This will initialize the version-level config with the base commit hash and the default mirror URL from the product-level config.
This will initialize the version-level config in `docker-images/druid/stackable/patches/28.0.0/patchable.toml` with the base commit hash and the default mirror URL from the product-level config.
You can optionally provide the `--ssh` flag to use SSH instead of HTTPS for Git operations.

## Glossary
Expand Down
116 changes: 95 additions & 21 deletions rust/patchable/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,24 +180,10 @@ enum Cmd {
pv: ProductVersion,
},

/// Creates a patchable.toml for a given product version
/// Creates patchable.toml configuration files
Init {
#[clap(flatten)]
pv: ProductVersion,

/// The upstream commit-ish (such as druid-28.0.0) that the patch series applies to
///
/// Refs (such as tags and branches) will be resolved to commit IDs.
#[clap(long)]
base: String,

/// Mirror the product version to the default mirror repository
#[clap(long)]
mirror: bool,

/// Use SSH for git operations
#[clap(long)]
ssh: bool,
#[clap(subcommand)]
init_type: InitCmd,
},

/// Shows the patch directory for a given product version
Expand All @@ -218,6 +204,41 @@ enum Cmd {
ImagesDir,
}

#[derive(clap::Parser)]
enum InitCmd {
/// Creates a patchable.toml for a given product
Product {
/// The product name slug (such as druid)
product: String,
/// The upstream repository URL (e.g. https://github.com/apache/druid.git)
#[clap(long)]
upstream: String,
/// The default mirror repository URL (e.g. https://github.com/stackabletech/druid.git)
#[clap(long)]
default_mirror: Option<String>,
},

/// Creates a patchable.toml for a given product version
Version {
#[clap(flatten)]
pv: ProductVersion,

/// The upstream commit-ish (such as druid-28.0.0) that the patch series applies to
///
/// Refs (such as tags and branches) will be resolved to commit IDs.
#[clap(long)]
base: String,

/// Mirror the product version to the default mirror repository
#[clap(long)]
mirror: bool,

/// Use SSH for git operations
#[clap(long)]
ssh: bool,
},
}

#[derive(Debug, Snafu)]
pub enum Error {
#[snafu(display("failed to configure git logging"))]
Expand Down Expand Up @@ -475,10 +496,61 @@ fn main() -> Result<()> {
}

Cmd::Init {
pv,
base,
mirror,
ssh,
init_type:
InitCmd::Product {
product,
upstream,
default_mirror,
},
} => {
let product_config_path = ProductVersionContext {
pv: ProductVersion {
product: product.clone(),
version: "".to_string(),
},
images_repo_root,
}
.product_config_path();

tracing::info!(
path = ?product_config_path,
"creating product configuration directory and file"
);

if let Some(product_config_dir) = product_config_path.parent() {
std::fs::create_dir_all(product_config_dir).context(CreatePatchDirSnafu {
path: product_config_dir,
})?;
}

let product_config = ProductConfig {
upstream,
default_mirror,
};

let config_toml =
toml::to_string_pretty(&product_config).context(SerializeConfigSnafu)?;
File::create_new(&product_config_path)
.and_then(|mut f| f.write_all(config_toml.as_bytes()))
.context(SaveConfigSnafu {
path: &product_config_path,
})?;

tracing::info!(
config.path = ?product_config_path,
product = product,
"created configuration for product"
);
}

Cmd::Init {
init_type:
InitCmd::Version {
pv,
base,
mirror,
ssh,
},
} => {
let ctx = ProductVersionContext {
pv,
Expand Down Expand Up @@ -510,6 +582,7 @@ fn main() -> Result<()> {
let mirror_url = if mirror {
let mut mirror_url = config
.default_mirror
.filter(|s| !s.is_empty())
.context(InitMirrorNotConfiguredSnafu)?;
if ssh {
mirror_url =
Expand Down Expand Up @@ -572,6 +645,7 @@ fn main() -> Result<()> {
std::fs::create_dir_all(config_dir)
.context(CreatePatchDirSnafu { path: config_dir })?;
}

let config_toml = toml::to_string_pretty(&config).context(SerializeConfigSnafu)?;
File::create_new(&config_path)
.and_then(|mut f| f.write_all(config_toml.as_bytes()))
Expand Down