Skip to content

Commit

Permalink
Merge pull request #47 from skipkayhil/hm-no-versions
Browse files Browse the repository at this point in the history
Remove hardcoded Ruby/Rails versions, add `--rebuild` flag
  • Loading branch information
rafaelfranca authored Jan 16, 2025
2 parents 7ba18e0 + 262dc86 commit bf3494d
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 22 deletions.
136 changes: 124 additions & 12 deletions src/docker_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,23 @@ pub struct DockerClient {}
impl DockerClient {
pub fn build_image(
ruby_version: &str,
rails_version: &str,
maybe_rails_version: Option<&str>,
user_id: Option<u32>,
group_id: Option<u32>,
rebuild: bool,
) -> Command {
let mut command = Command::new("docker");

command.arg("build");

if rebuild {
command.arg("--no-cache");
}

Self::set_build_arg(&mut command, "RUBY_VERSION", ruby_version);
Self::set_build_arg(&mut command, "RAILS_VERSION", rails_version);
if let Some(rails_version) = maybe_rails_version {
Self::set_build_arg(&mut command, "RAILS_VERSION", rails_version);
}

if let Some(id) = user_id {
Self::set_build_arg(&mut command, "USER_ID", &id.to_string())
Expand All @@ -25,14 +32,18 @@ impl DockerClient {

command.arg("-t");

Self::set_image_name(&mut command, ruby_version, rails_version);
Self::set_image_name(&mut command, ruby_version, maybe_rails_version);

command.arg("-").stdin(Stdio::piped());

command
}

pub fn run_image(ruby_version: &str, rails_version: &str, args: Vec<String>) -> Command {
pub fn run_image(
ruby_version: &str,
rails_version: Option<&str>,
args: Vec<String>,
) -> Command {
let mut command = Self::run();

Self::set_workdir(&mut command);
Expand All @@ -42,7 +53,7 @@ impl DockerClient {
command
}

pub fn get_help(ruby_version: &str, rails_version: &str) -> Command {
pub fn get_help(ruby_version: &str, rails_version: Option<&str>) -> Command {
let mut command = Self::run();

Self::set_image_name(&mut command, ruby_version, rails_version);
Expand Down Expand Up @@ -76,8 +87,16 @@ impl DockerClient {
.args(["-w", current_dir]);
}

fn set_image_name(command: &mut Command, ruby_version: &str, rails_version: &str) {
command.arg(format!("rails-new-{}-{}", ruby_version, rails_version));
fn set_image_name(
command: &mut Command,
ruby_version: &str,
maybe_rails_version: Option<&str>,
) {
if let Some(rails_version) = maybe_rails_version {
command.arg(format!("rails-new-{}-{}", ruby_version, rails_version));
} else {
command.arg(format!("rails-new-{}", ruby_version));
}
}

fn set_rails_new(command: &mut Command, args: Vec<String>) {
Expand Down Expand Up @@ -116,7 +135,7 @@ mod tests {

#[test]
fn build_image() {
let command = DockerClient::build_image("3.2.3", "7.1.3", None, None);
let command = DockerClient::build_image("3.2.3", Some("7.1.3"), None, None, false);

assert_eq!(command.get_program(), "docker");

Expand All @@ -139,7 +158,7 @@ mod tests {

#[test]
fn build_image_with_user_id() {
let command = DockerClient::build_image("3.2.3", "7.1.3", Some(1000), None);
let command = DockerClient::build_image("3.2.3", Some("7.1.3"), Some(1000), None, false);

assert_eq!(command.get_program(), "docker");

Expand All @@ -164,7 +183,7 @@ mod tests {

#[test]
fn build_image_with_group_id() {
let command = DockerClient::build_image("3.2.3", "7.1.3", None, Some(1000));
let command = DockerClient::build_image("3.2.3", Some("7.1.3"), None, Some(1000), false);

assert_eq!(command.get_program(), "docker");

Expand All @@ -187,9 +206,75 @@ mod tests {
);
}

#[test]
fn build_image_with_rebuild_flag() {
let command = DockerClient::build_image("3.2.3", Some("7.1.3"), None, None, true);

let args: Vec<&OsStr> = command.get_args().collect();

assert_eq!(
args,
&[
"build",
"--no-cache",
"--build-arg",
"RUBY_VERSION=3.2.3",
"--build-arg",
"RAILS_VERSION=7.1.3",
"-t",
"rails-new-3.2.3-7.1.3",
"-",
]
);
}

#[test]
fn build_image_without_rails_version() {
let command = DockerClient::build_image("3.2.3", None, None, None, false);

let args: Vec<&OsStr> = command.get_args().collect();

assert_eq!(
args,
&[
"build",
"--build-arg",
"RUBY_VERSION=3.2.3",
"-t",
"rails-new-3.2.3",
"-",
]
);
}

#[test]
fn build_image_with_both_ids() {
let command = DockerClient::build_image("3.2.3", Some("7.1.3"), Some(1000), Some(1000), false);

let args: Vec<&OsStr> = command.get_args().collect();

assert_eq!(
args,
&[
"build",
"--build-arg",
"RUBY_VERSION=3.2.3",
"--build-arg",
"RAILS_VERSION=7.1.3",
"--build-arg",
"USER_ID=1000",
"--build-arg",
"GROUP_ID=1000",
"-t",
"rails-new-3.2.3-7.1.3",
"-",
]
);
}

#[test]
fn run_image() {
let command = DockerClient::run_image("3.2.3", "7.1.3", vec!["my_app".to_string()]);
let command = DockerClient::run_image("3.2.3", Some("7.1.3"), vec!["my_app".to_string()]);

assert_eq!(command.get_program(), "docker");

Expand All @@ -216,9 +301,36 @@ mod tests {
);
}

#[test]
fn run_image_without_rails_version() {
let command = DockerClient::run_image("3.2.3", None, vec!["my_app".to_string()]);

let binding = current_dir().unwrap();
let absolute_path = canonicalize_os_path(&binding).unwrap();
let current_dir = absolute_path.to_str().unwrap();

let args: Vec<&OsStr> = command.get_args().collect();

assert_eq!(
args,
&[
"run",
"--rm",
"-v",
&format!("{}:{}", current_dir, current_dir),
"-w",
current_dir,
"rails-new-3.2.3",
"rails",
"new",
"my_app",
]
);
}

#[test]
fn get_help() {
let command = DockerClient::get_help("3.2.3", "7.1.3");
let command = DockerClient::get_help("3.2.3", Some("7.1.3"));

assert_eq!(command.get_program(), "docker");

Expand Down
10 changes: 6 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@ fn main() {
let cli = Cli::parse();

let ruby_version = cli.ruby_version;
let rails_version = cli.rails_version;
let rails_version = cli.rails_version.as_deref();
let rebuild = cli.rebuild;

// Run docker build --build-arg RUBY_VERSION=$RUBY_VERSION --build-arg RAILS_VERSION=$RAILS_VERSION -t rails-new-$RUBY_VERSION-$RAILS_VERSION
// passing the content of DOCKERFILE to the command stdin
let mut child = DockerClient::build_image(
&ruby_version,
&rails_version,
rails_version,
os_specific::get_user_id(),
os_specific::get_group_id(),
rebuild,
)
.spawn()
.expect("Failed to execute process");
Expand All @@ -44,12 +46,12 @@ fn main() {

match &cli.command {
Some(Commands::RailsHelp {}) => {
command = DockerClient::get_help(&ruby_version, &rails_version)
command = DockerClient::get_help(&ruby_version, rails_version)
}

None => {
// Run the image with docker run -v $(pwd):/$(pwd) -w $(pwd) rails-new-$RUBY_VERSION-$RAILS_VERSION rails new $@
command = DockerClient::run_image(&ruby_version, &rails_version, cli.args)
command = DockerClient::run_image(&ruby_version, rails_version, cli.args)
}
}

Expand Down
60 changes: 54 additions & 6 deletions src/rails_new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ pub struct Cli {
#[clap(trailing_var_arg = true, required = true)]
/// arguments passed to `rails new`
pub args: Vec<String>,
#[clap(long, short = 'u', default_value = "3.4.1")]
#[clap(long, short = 'u', default_value = "latest")]
pub ruby_version: String,
#[clap(long, short = 'r', default_value = "8.0.1")]
pub rails_version: String,
#[clap(long, short = 'r')]
pub rails_version: Option<String>,
#[clap(long)]
pub rebuild: bool,

#[command(subcommand)]
pub command: Option<Commands>,
Expand Down Expand Up @@ -52,10 +54,8 @@ mod tests {
let m = Cli::command().get_matches_from(vec!["rails-new", "my_app"]);

let ruby_version = m.get_one::<String>("ruby_version").unwrap();
let rails_version = m.get_one::<String>("rails_version").unwrap();

assert_eq!(ruby_version, "3.4.1");
assert_eq!(rails_version, "8.0.1");
assert_eq!(ruby_version, "latest");

Ok(())
}
Expand All @@ -73,4 +73,52 @@ mod tests {

Ok(())
}

#[test]
fn custom_ruby_version() -> Result<(), Box<dyn std::error::Error>> {
use clap::CommandFactory;

let m = Cli::command().get_matches_from(vec!["rails-new", "--ruby-version", "3.2.0", "my_app"]);
let ruby_version = m.get_one::<String>("ruby_version").unwrap();
assert_eq!(ruby_version, "3.2.0");

// Test short form
let m = Cli::command().get_matches_from(vec!["rails-new", "-u", "3.2.0", "my_app"]);
let ruby_version = m.get_one::<String>("ruby_version").unwrap();
assert_eq!(ruby_version, "3.2.0");

Ok(())
}

#[test]
fn rails_version_flag() -> Result<(), Box<dyn std::error::Error>> {
use clap::CommandFactory;

let m = Cli::command().get_matches_from(vec!["rails-new", "--rails-version", "7.1.0", "my_app"]);
let rails_version = m.get_one::<String>("rails_version").unwrap();
assert_eq!(rails_version, "7.1.0");

// Test short form
let m = Cli::command().get_matches_from(vec!["rails-new", "-r", "7.1.0", "my_app"]);
let rails_version = m.get_one::<String>("rails_version").unwrap();
assert_eq!(rails_version, "7.1.0");

Ok(())
}

#[test]
fn rebuild_flag() -> Result<(), Box<dyn std::error::Error>> {
use clap::CommandFactory;

let m = Cli::command().get_matches_from(vec!["rails-new", "--rebuild", "my_app"]);
let rebuild = m.get_flag("rebuild");
assert!(rebuild);

// Test default value (false)
let m = Cli::command().get_matches_from(vec!["rails-new", "my_app"]);
let rebuild = m.get_flag("rebuild");
assert!(!rebuild);

Ok(())
}
}

0 comments on commit bf3494d

Please sign in to comment.