Skip to content

Commit

Permalink
Merge pull request #57 from railwayapp/jr/provider-path-envs
Browse files Browse the repository at this point in the history
Python virtualenvs and provider paths
  • Loading branch information
coffee-cup authored Apr 29, 2022
2 parents c0564c1 + be8989d commit 6164f72
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 6 deletions.
1 change: 1 addition & 0 deletions examples/python/Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: gunicorn main:app
8 changes: 8 additions & 0 deletions src/nixpacks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,12 @@ impl<'a> AppBuilder<'a> {
.map(|cmd| format!("RUN {}", cmd))
.unwrap_or_else(|| "".to_string());

let path_env = if let Some(paths) = install_phase.paths {
format!("ENV PATH {}:$PATH", paths.join(":"))
} else {
"".to_string()
};

// Files to copy for install phase
// If none specified, copy over the entire app
let install_files = install_phase
Expand Down Expand Up @@ -500,6 +506,7 @@ impl<'a> AppBuilder<'a> {
# Install
{install_copy_cmd}
{install_cmd}
{path_env}
# Build
{build_copy_cmd}
Expand All @@ -514,6 +521,7 @@ impl<'a> AppBuilder<'a> {
args_string=args_string,
install_copy_cmd=get_copy_command(&install_files, app_dir),
install_cmd=install_cmd,
path_env=path_env,
build_copy_cmd=get_copy_command(&build_files, app_dir),
build_cmd=build_cmd,
start_copy_cmd=get_copy_command(&start_files, app_dir),
Expand Down
12 changes: 12 additions & 0 deletions src/nixpacks/phase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,16 @@ pub struct InstallPhase {

#[serde(rename = "onlyIncludeFiles")]
pub only_include_files: Option<Vec<String>>,

pub paths: Option<Vec<String>>,
}

impl InstallPhase {
pub fn new(cmd: String) -> Self {
Self {
cmd: Some(cmd),
only_include_files: None,
paths: None,
}
}

Expand All @@ -64,6 +67,15 @@ impl InstallPhase {
self.only_include_files = Some(vec![file]);
}
}

pub fn add_path(&mut self, path: String) {
if let Some(mut paths) = self.paths.clone() {
paths.push(path);
self.paths = Some(paths);
} else {
self.paths = Some(vec![path]);
}
}
}

#[serde_with::skip_serializing_none]
Expand Down
19 changes: 15 additions & 4 deletions src/providers/python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,28 @@ impl Provider for PythonProvider {
}

fn install(&self, app: &App, _env: &Environment) -> Result<Option<InstallPhase>> {
let env_loc = "/opt/venv";
let create_env = format!("python -m venv {}", env_loc);
let activate_env = format!(". {}/bin/activate", env_loc);

if app.includes_file("requirements.txt") {
let mut install_phase = InstallPhase::new(
"python -m ensurepip && python -m pip install -r requirements.txt".to_string(),
);
let mut install_phase = InstallPhase::new(format!(
"{} && {} && pip install -r requirements.txt",
create_env, activate_env
));
install_phase.add_file_dependency("requirements.txt".to_string());
install_phase.add_path(format!("{}/bin", env_loc));
return Ok(Some(install_phase));
} else if app.includes_file("pyproject.toml") {
let mut install_phase =InstallPhase::new("python -m ensurepip && python -m pip install --upgrade build setuptools && python -m pip install .".to_string());
let mut install_phase = InstallPhase::new(format!(
"{} && {} && pip install --upgrade build setuptools && pip install .",
create_env, activate_env
));
install_phase.add_file_dependency("pyproject.toml".to_string());
install_phase.add_path(format!("{}/bin", env_loc));
return Ok(Some(install_phase));
}

Ok(None)
}

Expand Down
7 changes: 5 additions & 2 deletions tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,9 +216,12 @@ pub fn test_python() -> Result<()> {
assert_eq!(plan.build.unwrap().cmd, None);
assert_eq!(
plan.install.unwrap().cmd,
Some("python -m ensurepip && python -m pip install -r requirements.txt".to_string())
Some("python -m venv /opt/venv && . /opt/venv/bin/activate && pip install -r requirements.txt".to_string())
);
assert_eq!(
plan.start.unwrap().cmd,
Some("gunicorn main:app".to_string())
);
assert_eq!(plan.start.unwrap().cmd, Some("python main.py".to_string()));

Ok(())
}
Expand Down

0 comments on commit 6164f72

Please sign in to comment.