Add support for mono-repo with multiple build context

This commit is contained in:
Romain GERARD
2021-06-09 17:13:17 +02:00
committed by Erèbe - Romain Gerard
parent 0eaa7dcb0c
commit cea0a3d80d
4 changed files with 117 additions and 122 deletions

View File

@@ -299,77 +299,55 @@ impl BuildPlatform for LocalDocker {
}
// git clone
let into_dir = workspace_directory(
let repository_root_path = workspace_directory(
self.context.workspace_root_dir(),
self.context.execution_id(),
format!("build/{}", build.image.name.as_str()),
);
info!("cloning repository: {}", build.git_repository.url);
info!(
"cloning repository: {} to {}",
build.git_repository.url, repository_root_path
);
let git_clone = git::clone(
build.git_repository.url.as_str(),
&into_dir,
&repository_root_path,
&build.git_repository.credentials,
);
match git_clone {
Ok(_) => {}
Err(err) => {
let message = format!(
"Error while cloning repository {}. Error: {:?}",
&build.git_repository.url, err
);
error!("{}", message);
return Err(self.engine_error(EngineErrorCause::Internal, message));
}
if let Err(err) = git_clone {
let message = format!(
"Error while cloning repository {}. Error: {:?}",
&build.git_repository.url, err
);
error!("{}", message);
return Err(self.engine_error(EngineErrorCause::Internal, message));
}
// git checkout to given commit
let repo = &git_clone.unwrap();
let repo = git_clone.unwrap();
let commit_id = &build.git_repository.commit_id;
match git::checkout(&repo, &commit_id, build.git_repository.url.as_str()) {
Ok(_) => {}
Err(err) => {
let message = format!(
"Error while git checkout repository {} with commit id {}. Error: {:?}",
&build.git_repository.url, commit_id, err
);
error!("{}", message);
return Err(self.engine_error(EngineErrorCause::Internal, message));
}
if let Err(err) = git::checkout(&repo, commit_id, build.git_repository.url.as_str()) {
let message = format!(
"Error while git checkout repository {} with commit id {}. Error: {:?}",
&build.git_repository.url, commit_id, err
);
error!("{}", message);
return Err(self.engine_error(EngineErrorCause::Internal, message));
}
// git checkout submodules
match checkout_submodules(repo) {
Ok(_) => {}
Err(err) => {
let message = format!(
"Error while checkout submodules from repository {}. Error: {:?}",
&build.git_repository.url, err
);
if let Err(err) = checkout_submodules(&repo) {
let message = format!(
"Error while checkout submodules from repository {}. Error: {:?}",
&build.git_repository.url, err
);
error!("{}", message);
error!("{}", message);
return Err(self.engine_error(EngineErrorCause::Internal, message));
}
return Err(self.engine_error(EngineErrorCause::Internal, message));
}
let into_dir_docker_style = format!("{}/.", into_dir.as_str());
let dockerfile_relative_path = match &build.git_repository.dockerfile_path {
Some(dockerfile_relative_path) => match dockerfile_relative_path.trim() {
"" | "." | "/" | "/." | "./" | "Dockerfile" => Some("Dockerfile"),
dockerfile_root_path => Some(dockerfile_root_path),
},
None => None,
};
let mut disable_build_cache = false;
let mut env_var_args: Vec<String> = Vec::with_capacity(build.options.environment_variables.len());
for ev in &build.options.environment_variables {
@@ -407,48 +385,67 @@ impl BuildPlatform for LocalDocker {
}
}
let application_id = build.image.application_id.clone();
let app_id = build.image.application_id.clone();
let build_context_path = format!("{}/{}/.", repository_root_path.as_str(), build.git_repository.root_path);
// If no Dockerfile specified, we should use BuildPacks
let result = if build.git_repository.dockerfile_path.is_some() {
// build container from the provided Dockerfile
let dockerfile_exists = match dockerfile_relative_path {
Some(path) => {
let dockerfile_complete_path = format!("{}/{}", into_dir.as_str(), path);
let exists = Path::new(dockerfile_complete_path.as_str()).exists();
if !exists {
warn!("Dockerfile not found under given {}", dockerfile_complete_path)
}
exists
}
None => false,
};
let dockerfile_relative_path = build.git_repository.dockerfile_path.as_ref().unwrap();
let dockerfile_normalized_path = match dockerfile_relative_path.trim() {
"" | "." | "/" | "/." | "./" | "Dockerfile" => "Dockerfile",
dockerfile_root_path => dockerfile_root_path,
};
let result = match dockerfile_exists {
true => {
// build container from the provided Dockerfile
let dockerfile_complete_path = format!("{}/{}", into_dir.as_str(), dockerfile_relative_path.unwrap());
let dockerfile_relative_path = format!("{}/{}", build.git_repository.root_path, dockerfile_normalized_path);
let dockerfile_absolute_path = format!("{}/{}", repository_root_path.as_str(), dockerfile_relative_path);
self.build_image_with_docker(
build,
dockerfile_complete_path.as_str(),
into_dir_docker_style.as_str(),
env_var_args,
!disable_build_cache,
&listeners_helper,
)
}
false => {
// build container with Buildpacks
self.build_image_with_buildpacks(
build,
into_dir_docker_style.as_str(),
env_var_args,
!disable_build_cache,
&listeners_helper,
)
// If the dockerfile does not exist, abort
if !Path::new(dockerfile_absolute_path.as_str()).exists() {
warn!("Dockerfile not found under {}", dockerfile_absolute_path);
listeners_helper.error(ProgressInfo::new(
ProgressScope::Application {
id: build.image.application_id.clone(),
},
ProgressLevel::Error,
Some(format!(
"Dockerfile is not present at location {}",
dockerfile_relative_path
)),
self.context.execution_id(),
));
return Err(self.engine_error(
EngineErrorCause::User("Dockerfile not found at location"),
format!(
"Your Dockerfile is not present at the specified location {}/{}",
build.git_repository.root_path.as_str(),
build.git_repository.dockerfile_path.unwrap_or_default().as_str()
),
));
}
self.build_image_with_docker(
build,
dockerfile_absolute_path.as_str(),
build_context_path.as_str(),
env_var_args,
!disable_build_cache,
&listeners_helper,
)
} else {
// build container with Buildpacks
self.build_image_with_buildpacks(
build,
build_context_path.as_str(),
env_var_args,
!disable_build_cache,
&listeners_helper,
)
};
listeners_helper.deployment_in_progress(ProgressInfo::new(
ProgressScope::Application { id: application_id },
ProgressScope::Application { id: app_id },
ProgressLevel::Info,
Some(format!("container {} is built ✔", self.name_with_id())),
self.context.execution_id(),

View File

@@ -50,6 +50,7 @@ pub struct GitRepository {
pub credentials: Option<Credentials>,
pub commit_id: String,
pub dockerfile_path: Option<String>,
pub root_path: String,
}
#[derive(Clone, Eq, PartialEq, Hash, Debug)]

View File

@@ -142,6 +142,10 @@ impl Action {
}
}
fn default_root_path_value() -> String {
"/".to_string()
}
#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Hash)]
pub struct Application {
pub id: String,
@@ -152,6 +156,8 @@ pub struct Application {
pub branch: String,
pub commit_id: String,
pub dockerfile_path: Option<String>,
#[serde(default = "default_root_path_value")]
pub root_path: String,
pub private_port: Option<u16>,
pub total_cpus: String,
pub cpu_burst: String,
@@ -285,15 +291,13 @@ impl Application {
Build {
git_repository: GitRepository {
url: self.git_url.clone(),
credentials: match &self.git_credentials {
Some(credentials) => Some(Credentials {
login: credentials.login.clone(),
password: credentials.access_token.clone(),
}),
_ => None,
},
credentials: self.git_credentials.as_ref().map(|credentials| Credentials {
login: credentials.login.clone(),
password: credentials.access_token.clone(),
}),
commit_id: self.commit_id.clone(),
dockerfile_path: self.dockerfile_path.clone(),
root_path: self.root_path.clone(),
},
image: self.to_image(),
options: BuildOptions {
@@ -377,9 +381,7 @@ impl Storage {
crate::cloud_provider::models::Storage {
id: self.id.clone(),
name: self.name.clone(),
storage_type: match self.storage_type {
_ => crate::cloud_provider::digitalocean::application::StorageType::Standard,
},
storage_type: crate::cloud_provider::digitalocean::application::StorageType::Standard,
size_in_gib: self.size_in_gib,
mount_point: self.mount_point.clone(),
snapshot_retention_in_days: self.snapshot_retention_in_days,
@@ -771,13 +773,10 @@ impl ExternalService {
Build {
git_repository: GitRepository {
url: self.git_url.clone(),
credentials: match &self.git_credentials {
Some(credentials) => Some(Credentials {
login: credentials.login.clone(),
password: credentials.access_token.clone(),
}),
_ => None,
},
credentials: self.git_credentials.as_ref().map(|credentials| Credentials {
login: credentials.login.clone(),
password: credentials.access_token.clone(),
}),
commit_id: self.commit_id.clone(),
dockerfile_path: Some(match self.action {
Action::Create => self.on_create_dockerfile_path.clone(),
@@ -785,6 +784,7 @@ impl ExternalService {
Action::Delete => self.on_delete_dockerfile_path.clone(),
Action::Nothing => self.on_create_dockerfile_path.clone(),
}),
root_path: default_root_path_value(),
},
image: self.to_image(),
options: BuildOptions {
@@ -826,10 +826,7 @@ impl ProgressInfo {
created_at: Utc::now(),
scope,
level,
message: match message {
Some(msg) => Some(msg.into()),
_ => None,
},
message: message.map(|msg| msg.into()),
execution_id: execution_id.into(),
}
}
@@ -1015,20 +1012,14 @@ impl Context {
pub fn is_dry_run_deploy(&self) -> bool {
match &self.metadata {
Some(meta) => match meta.dry_run_deploy {
Some(true) => true,
_ => false,
},
Some(meta) => matches!(meta.dry_run_deploy, Some(true)),
_ => false,
}
}
pub fn requires_forced_upgrade(&self) -> bool {
match &self.metadata {
Some(meta) => match meta.forced_upgrade {
Some(true) => true,
_ => false,
},
Some(meta) => matches!(meta.forced_upgrade, Some(true)),
_ => false,
}
}
@@ -1039,20 +1030,17 @@ impl Context {
pub fn resource_expiration_in_seconds(&self) -> Option<u32> {
match &self.metadata {
Some(meta) => match meta.resource_expiration_in_seconds {
Some(ttl) => Some(ttl),
_ => None,
},
Some(meta) => meta.resource_expiration_in_seconds.map(|ttl| ttl),
_ => None,
}
}
pub fn docker_build_options(&self) -> Option<Vec<String>> {
match &self.metadata {
Some(meta) => match meta.docker_build_options.clone() {
Some(b) => Some(b.split(" ").map(|x| x.to_string()).collect()),
_ => None,
},
Some(meta) => meta
.docker_build_options
.clone()
.map(|b| b.split(' ').map(|x| x.to_string()).collect()),
_ => None,
}
}

View File

@@ -324,6 +324,7 @@ pub fn environment_3_apps_3_routers_3_databases(context: &Context, secrets: Func
git_url: "https://github.com/Qovery/engine-testing.git".to_string(),
commit_id: "5990752647af11ef21c3d46a51abbde3da1ab351".to_string(),
dockerfile_path: Some("Dockerfile".to_string()),
root_path: "/".to_string(),
action: Action::Create,
git_credentials: Some(GitCredentials {
login: "x-access-token".to_string(),
@@ -374,6 +375,7 @@ pub fn environment_3_apps_3_routers_3_databases(context: &Context, secrets: Func
git_url: "https://github.com/Qovery/engine-testing.git".to_string(),
commit_id: "5990752647af11ef21c3d46a51abbde3da1ab351".to_string(),
dockerfile_path: Some("Dockerfile".to_string()),
root_path: String::from("/"),
action: Action::Create,
git_credentials: Some(GitCredentials {
login: "x-access-token".to_string(),
@@ -425,6 +427,7 @@ pub fn environment_3_apps_3_routers_3_databases(context: &Context, secrets: Func
commit_id: "158ea8ebc9897c50a7c56b910db33ce837ac1e61".to_string(),
dockerfile_path: Some(format!("Dockerfile-{}", version_mongo)),
action: Action::Create,
root_path: String::from("/"),
git_credentials: Some(GitCredentials {
login: "x-access-token".to_string(),
access_token: "xxx".to_string(),
@@ -590,6 +593,7 @@ pub fn working_minimal_environment(context: &Context, secrets: FuncTestsSecrets)
git_url: "https://github.com/Qovery/engine-testing.git".to_string(),
commit_id: "fc575a2f3be0b9100492c8a463bf18134a8698a5".to_string(),
dockerfile_path: Some("Dockerfile".to_string()),
root_path: String::from("/"),
action: Action::Create,
git_credentials: Some(GitCredentials {
login: "x-access-token".to_string(),
@@ -670,6 +674,7 @@ pub fn environnement_2_app_2_routers_1_psql(context: &Context, secrets: FuncTest
git_url: "https://github.com/Qovery/engine-testing.git".to_string(),
commit_id: "680550d1937b3f90551849c0da8f77c39916913b".to_string(),
dockerfile_path: Some("Dockerfile".to_string()),
root_path: String::from("/"),
action: Action::Create,
git_credentials: Some(GitCredentials {
login: "x-access-token".to_string(),
@@ -720,6 +725,7 @@ pub fn environnement_2_app_2_routers_1_psql(context: &Context, secrets: FuncTest
git_url: "https://github.com/Qovery/engine-testing.git".to_string(),
commit_id: "680550d1937b3f90551849c0da8f77c39916913b".to_string(),
dockerfile_path: Some("Dockerfile".to_string()),
root_path: String::from("/"),
action: Action::Create,
git_credentials: Some(GitCredentials {
login: "x-access-token".to_string(),
@@ -833,6 +839,7 @@ pub fn echo_app_environment(context: &Context, secrets: FuncTestsSecrets) -> Env
git_url: "https://github.com/Qovery/engine-testing.git".to_string(),
commit_id: "2205adea1db295547b99f7b17229afd7e879b6ff".to_string(),
dockerfile_path: Some("Dockerfile".to_string()),
root_path: String::from("/"),
action: Action::Create,
git_credentials: Some(GitCredentials {
login: "x-access-token".to_string(),
@@ -887,6 +894,7 @@ pub fn environment_only_http_server(context: &Context) -> Environment {
git_url: "https://github.com/Qovery/engine-testing.git".to_string(),
commit_id: "a873edd459c97beb51453db056c40bca85f36ef9".to_string(),
dockerfile_path: Some("Dockerfile".to_string()),
root_path: String::from("/"),
action: Action::Create,
git_credentials: Some(GitCredentials {
login: "x-access-token".to_string(),
@@ -927,6 +935,7 @@ pub fn environment_only_http_server_router(context: &Context, secrets: FuncTests
git_url: "https://github.com/Qovery/engine-testing.git".to_string(),
commit_id: "a873edd459c97beb51453db056c40bca85f36ef9".to_string(),
dockerfile_path: Some("Dockerfile".to_string()),
root_path: String::from("/"),
action: Action::Create,
git_credentials: Some(GitCredentials {
login: "x-access-token".to_string(),