Skip to content

Commit

Permalink
Merge pull request #47 from golemcloud/vigoo/expose-cli-module
Browse files Browse the repository at this point in the history
Expose parts of the CLI implementation
  • Loading branch information
vigoo authored Aug 9, 2024
2 parents 95a7ae2 + 3d6e330 commit 14239d9
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 75 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
- name: Tests
run: cargo test --all-features
- name: List bundled examples
run: cargo run --features=build-binary list-examples
run: cargo run list-examples
publish:
needs: [ build ]
if: "startsWith(github.ref, 'refs/tags/v')"
Expand Down
7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ copy_dir = "0.1.3"
dir-diff = "0.3.3"

[features]
build-binary = ["clap"]
default = ["cli"]
cli = ["dep:clap"]

[lib]
path = "src/lib.rs"

[[bin]]
name = "golem-examples-cli"
path = "src/cli.rs"
required-features = ["build-binary"]
path = "src/main.rs"
required-features = ["cli"]
100 changes: 29 additions & 71 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,106 +1,64 @@
use clap::*;
use golem_examples::model::{
ComponentName, ExampleName, ExampleParameters, GuestLanguage, GuestLanguageTier, PackageName,
};
use golem_examples::*;
use std::env;

use crate::model::{ComponentName, ExampleName, GuestLanguage, GuestLanguageTier, PackageName};

#[derive(Args, Debug)]
#[group(required = true, multiple = false)]
struct NameOrLanguage {
pub struct NameOrLanguage {
/// Name of the example to use
#[arg(short, long, group = "ex")]
example: Option<ExampleName>,
pub example: Option<ExampleName>,

/// Language to use for it's default example
#[arg(short, long, alias = "lang", group = "ex")]
language: Option<GuestLanguage>,
pub language: Option<GuestLanguage>,
}

impl NameOrLanguage {
/// Gets the selected example's name
pub fn example_name(&self) -> ExampleName {
self.example
.clone()
.unwrap_or(ExampleName::from_string(format!(
"{}-default",
self.language.clone().unwrap_or(GuestLanguage::Rust).id()
)))
}
}

#[derive(Subcommand, Debug)]
#[command()]
enum Command {
pub enum Command {
/// Create a new Golem component from built-in examples
#[command()]
New {
#[command(flatten)]
name_or_language: NameOrLanguage,

/// The package name of the generated component (in namespace:name format)
#[arg(short, long)]
package_name: Option<PackageName>,

/// The new component's name
component_name: ComponentName,
},

/// Lists the built-in examples available for creating new components
#[command()]
ListExamples {
/// The minimum language tier to include in the list
#[arg(short, long)]
min_tier: Option<GuestLanguageTier>,

/// Filter examples by a given guest language
#[arg(short, long, alias = "lang")]
language: Option<GuestLanguage>,
},
}

#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None, rename_all = "kebab-case")]
struct GolemCommand {
pub struct GolemCommand {
#[command(subcommand)]
command: Command,
}

pub fn main() {
let command: GolemCommand = GolemCommand::parse();
match &command.command {
Command::New {
name_or_language,
component_name,
package_name,
} => {
let example_name =
name_or_language
.example
.clone()
.unwrap_or(ExampleName::from_string(format!(
"{}-default",
name_or_language
.language
.clone()
.unwrap_or(GuestLanguage::Rust)
.id()
)));
let examples = GolemExamples::list_all_examples();
let example = examples.iter().find(|example| example.name == example_name);
match example {
Some(example) => {
let cwd = env::current_dir().expect("Failed to get current working directory");
match GolemExamples::instantiate(
example,
ExampleParameters {
component_name: component_name.clone(),
package_name: package_name
.clone()
.unwrap_or(PackageName::from_string("golem:component").unwrap()),
target_path: cwd,
},
) {
Ok(instructions) => println!("{instructions}"),
Err(err) => eprintln!("Failed to instantiate example: {err}"),
}
}
None => {
eprintln!("Unknown example {example_name}. Use the list-examples command to see the available commands.");
}
}
}
Command::ListExamples { min_tier, language } => {
GolemExamples::list_all_examples()
.iter()
.filter(|example| match language {
Some(language) => example.language == *language,
None => true,
})
.filter(|example| match min_tier {
Some(min_tier) => example.language.tier() <= *min_tier,
None => true,
})
.for_each(|example| println!("{:?}", example));
}
}
pub command: Command,
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use std::io::Write;
use std::path::{Path, PathBuf};
use std::{fs, io};

#[cfg(feature = "cli")]
pub mod cli;
pub mod model;

pub trait Examples {
Expand Down
54 changes: 54 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use clap::Parser;
use golem_examples::cli::*;
use golem_examples::model::*;
use golem_examples::{Examples, GolemExamples};
use std::env;

pub fn main() {
let command: GolemCommand = GolemCommand::parse();
match &command.command {
Command::New {
name_or_language,
component_name,
package_name,
} => {
let example_name = name_or_language.example_name();
let examples = GolemExamples::list_all_examples();
let example = examples.iter().find(|example| example.name == example_name);
match example {
Some(example) => {
let cwd = env::current_dir().expect("Failed to get current working directory");
match GolemExamples::instantiate(
example,
ExampleParameters {
component_name: component_name.clone(),
package_name: package_name
.clone()
.unwrap_or(PackageName::from_string("golem:component").unwrap()),
target_path: cwd,
},
) {
Ok(instructions) => println!("{instructions}"),
Err(err) => eprintln!("Failed to instantiate example: {err}"),
}
}
None => {
eprintln!("Unknown example {example_name}. Use the list-examples command to see the available commands.");
}
}
}
Command::ListExamples { min_tier, language } => {
GolemExamples::list_all_examples()
.iter()
.filter(|example| match language {
Some(language) => example.language == *language,
None => true,
})
.filter(|example| match min_tier {
Some(min_tier) => example.language.tier() <= *min_tier,
None => true,
})
.for_each(|example| println!("{:?}", example));
}
}
}

0 comments on commit 14239d9

Please sign in to comment.