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
61 changes: 42 additions & 19 deletions vdev/src/commands/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,49 @@ mod markdown;
mod rust;
mod scripts;

crate::cli_subcommands! {
"Check parts of the Vector code base..."
changelog_fragments,
generated_docs,
component_features,
component_examples,
deny,
docs,
events,
examples,
fmt,
licenses,
markdown,
rust,
scripts,
use crate::utils::command::ScriptArgs;

/// Check parts of the Vector code base...
#[derive(clap::Args, Debug)]
pub(super) struct Cli {
#[command(subcommand)]
command: Commands,
}

// These should eventually be migrated to Rust code
#[derive(clap::Subcommand, Debug)]
enum Commands {
ChangelogFragments(changelog_fragments::Cli),
GeneratedDocs(generated_docs::Cli),
ComponentFeatures(component_features::Cli),
ComponentExamples(component_examples::Cli),
Deny(deny::Cli),
/// Check that all /docs files are valid
Docs(ScriptArgs),
Events(events::Cli),
Examples(examples::Cli),
Fmt(fmt::Cli),
Licenses(licenses::Cli),
Markdown(markdown::Cli),
Rust(rust::Cli),
Scripts(scripts::Cli),
}

crate::script_wrapper! {
docs = "Check that all /docs files are valid"
=> "check-docs.sh"
impl Cli {
pub fn exec(self) -> anyhow::Result<()> {
match self.command {
Commands::ChangelogFragments(cli) => cli.exec(),
Commands::GeneratedDocs(cli) => cli.exec(),
Commands::ComponentFeatures(cli) => cli.exec(),
Commands::ComponentExamples(cli) => cli.exec(),
Commands::Deny(cli) => cli.exec(),
Commands::Docs(args) => args.exec("check-docs.sh"),
Commands::Events(cli) => cli.exec(),
Commands::Examples(cli) => cli.exec(),
Commands::Fmt(cli) => cli.exec(),
Commands::Licenses(cli) => cli.exec(),
Commands::Markdown(cli) => cli.exec(),
Commands::Rust(cli) => cli.exec(),
Commands::Scripts(cli) => cli.exec(),
}
}
}
87 changes: 69 additions & 18 deletions vdev/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,25 +113,76 @@ cli_commands! {
version,
}

/// This macro creates a wrapper for an existing script.
#[macro_export]
macro_rules! script_wrapper {
( $mod:ident = $doc:literal => $script:literal ) => {
pastey::paste! {
mod $mod {
#[doc = $doc]
#[derive(clap::Args, Debug)]
#[command()]
pub(super) struct Cli {
args: Vec<String>,
}
#[cfg(test)]
mod tests {
use clap::{CommandFactory as _, error::ErrorKind};

impl Cli {
pub(super) fn exec(self) -> anyhow::Result<()> {
$crate::app::exec(concat!("scripts/", $script), self.args, true)
}
}
use super::Cli;

const SCRIPT_COMMANDS: &[(&str, &str)] = &[
("check", "docs"),
("package", "archive"),
("package", "deb"),
("package", "msi"),
("package", "rpm"),
("release", "docker"),
("release", "s3"),
];

#[test]
fn script_commands_forward_arguments() {
let cases: &[(&[&str], &[&str])] = &[
(&[], &[]),
(&["0.58.0"], &["0.58.0"]),
(
&["--chart-version", "0.46.0"],
&["--chart-version", "0.46.0"],
),
(&["--chart-version=0.46.0"], &["--chart-version=0.46.0"]),
(
&["-x", "path with spaces", "-1"],
&["-x", "path with spaces", "-1"],
),
(&["value", "--help", "-v"], &["value", "--help", "-v"]),
(&["--", "--help"], &["--help"]),
(
&["--", "--chart-version", "0.46.0"],
&["--chart-version", "0.46.0"],
),
];

for &(group, command) in SCRIPT_COMMANDS {
for &(args, expected) in cases {
let matches = Cli::command()
.try_get_matches_from(
["vdev", group, command]
.into_iter()
.chain(args.iter().copied()),
)
.unwrap_or_else(|error| panic!("{group} {command} {args:?}: {error}"));
let script = matches
.subcommand_matches(group)
.unwrap()
.subcommand_matches(command)
.unwrap();
let forwarded: Vec<_> = script
.get_many::<String>("args")
.into_iter()
.flatten()
.map(String::as_str)
.collect();
assert_eq!(forwarded, expected, "{group} {command} {args:?}");
}
}
};
}

#[test]
fn script_commands_keep_vdev_help() {
for &(group, command) in SCRIPT_COMMANDS {
let error = Cli::command()
.try_get_matches_from(["vdev", group, command, "--help"])
.unwrap_err();
assert_eq!(error.kind(), ErrorKind::DisplayHelp, "{group} {command}");
}
}
}
44 changes: 27 additions & 17 deletions vdev/src/commands/package.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
crate::cli_subcommands! {
"Package Vector in various formats..."
archive, deb, msi, rpm,
}
use crate::utils::command::ScriptArgs;

crate::script_wrapper! {
archive = "Create a .tar.gz package for the specified $TARGET"
=> "package-archive.sh"
}
crate::script_wrapper! {
deb = "Create a .deb package to be distributed in the APT package manager"
=> "package-deb.sh"
/// Package Vector in various formats...
#[derive(clap::Args, Debug)]
pub(super) struct Cli {
#[command(subcommand)]
command: Commands,
}
crate::script_wrapper! {
msi = "Create a .msi package for Windows"
=> "package-msi.sh"

#[derive(clap::Subcommand, Debug)]
enum Commands {
/// Create a .tar.gz package for the specified $TARGET
Archive(ScriptArgs),
/// Create a .deb package to be distributed in the APT package manager
Deb(ScriptArgs),
/// Create a .msi package for Windows
Msi(ScriptArgs),
/// Create a .rpm package to be distributed in the YUM package manager
Rpm(ScriptArgs),
}
crate::script_wrapper! {
rpm = "Create a .rpm package to be distributed in the YUM package manager"
=> "package-rpm.sh"

impl Cli {
pub fn exec(self) -> anyhow::Result<()> {
match self.command {
Commands::Archive(args) => args.exec("package-archive.sh"),
Commands::Deb(args) => args.exec("package-deb.sh"),
Commands::Msi(args) => args.exec("package-msi.sh"),
Commands::Rpm(args) => args.exec("package-rpm.sh"),
}
}
}
46 changes: 31 additions & 15 deletions vdev/src/commands/release/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ mod workflow;
use anyhow::{Result, ensure};
use semver::Version;

use crate::utils::command::ScriptArgs;

fn ensure_stable(version: &Version, label: &str) -> Result<()> {
ensure!(
version.pre.is_empty() && version.build.is_empty(),
Expand All @@ -23,22 +25,36 @@ fn preparation_branch(version: &Version) -> String {
)
}

crate::cli_subcommands! {
"Manage the release process..."
channel,
docker,
generate_cue,
github,
prepare,
workflow,
s3,
/// Manage the release process...
#[derive(clap::Args, Debug)]
pub(super) struct Cli {
#[command(subcommand)]
command: Commands,
}

crate::script_wrapper! {
docker = "Build the Vector docker images and optionally push it to the registry"
=> "build-docker.sh"
#[derive(clap::Subcommand, Debug)]
enum Commands {
Channel(channel::Cli),
/// Build the Vector docker images and optionally push it to the registry
Docker(ScriptArgs),
GenerateCue(generate_cue::Cli),
Github(github::Cli),
Prepare(prepare::Cli),
Workflow(workflow::Cli),
/// Uploads archives and packages to AWS S3
S3(ScriptArgs),
}
crate::script_wrapper! {
s3 = "Uploads archives and packages to AWS S3"
=> "release-s3.sh"

impl Cli {
pub fn exec(self) -> Result<()> {
match self.command {
Commands::Channel(cli) => cli.exec(),
Commands::Docker(args) => args.exec("build-docker.sh"),
Commands::GenerateCue(cli) => cli.exec(),
Commands::Github(cli) => cli.exec(),
Commands::Prepare(cli) => cli.exec(),
Commands::Workflow(cli) => cli.exec(),
Commands::S3(args) => args.exec("release-s3.sh"),
}
}
}
20 changes: 20 additions & 0 deletions vdev/src/utils/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,26 @@ use std::{
process::{self, Command},
};

use crate::app::CommandExt as _;

/// Arguments forwarded to a repository script.
#[derive(clap::Args, Debug)]
pub struct ScriptArgs {
/// Arguments passed to the script (use `-- --help` for the script's help).
#[arg(allow_hyphen_values = true, trailing_var_arg = true)]
args: Vec<String>,
}

impl ScriptArgs {
/// Run a script from the repository's scripts directory with the forwarded arguments.
pub fn exec(self, script: &str) -> anyhow::Result<()> {
Command::script(script)
.args(self.args)
.in_repo()
.check_run()
}
}

/// Trait for chaining command arguments
pub trait ChainArgs {
fn chain_args<I: Into<OsString>>(&self, args: impl IntoIterator<Item = I>) -> Vec<OsString>;
Expand Down
Loading