Skip to content

Commit 714dd3a

Browse files
committed
feat(toolchain): Implement dockerignore for remote builds
1 parent 1e67e85 commit 714dd3a

1 file changed

Lines changed: 64 additions & 5 deletions

File tree

packages/toolchain/toolchain/src/util/docker/build_remote.rs

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use anyhow::*;
22
use flate2::{write::GzEncoder, Compression};
33
use serde_json::json;
4-
use std::{collections::HashMap, io::Write, path::Path, result::Result::Ok, time::Duration};
4+
use std::{collections::HashMap, io::Write, path::{Path, PathBuf}, result::Result::Ok, time::Duration};
55
use tempfile::NamedTempFile;
66
use uuid::Uuid;
77

@@ -380,25 +380,84 @@ async fn get_or_create_ci_manager_actor(
380380
Ok((create_response.actor.id.to_string(), endpoint.clone()))
381381
}
382382

383+
/// Moves over build context to a temp directory,
384+
/// ignoring all .dockerignore files.
385+
fn prepare_build_context_dir(
386+
build_path: &Path,
387+
dockerfile_path: &Path
388+
) -> Result<Vec<PathBuf>> {
389+
const DOCKERIGNORE_FILENAME: &str = ".dockerignore";
390+
391+
let mut paths = Vec::new();
392+
393+
// For Kaniko on the remote build, we need to expose
394+
// our Dockerfile and our .dockerignore file if it
395+
// exists
396+
paths.push(dockerfile_path.to_path_buf());
397+
398+
let dockerignore_path = build_path.join(DOCKERIGNORE_FILENAME);
399+
if dockerignore_path.try_exists().unwrap_or(false) {
400+
paths.push(dockerignore_path.clone());
401+
}
402+
403+
let walk = ignore::WalkBuilder::new(build_path)
404+
.standard_filters(false)
405+
.add_custom_ignore_filename(DOCKERIGNORE_FILENAME)
406+
.parents(true)
407+
.build();
408+
409+
for entry in walk {
410+
let entry = entry?;
411+
412+
if entry.path() == dockerfile_path || entry.path() == &dockerignore_path {
413+
// Skip the Dockerfile or .dockerignore itself, we already added it
414+
continue;
415+
}
416+
417+
let is_file = entry.file_type()
418+
.map(|ft| ft.is_file())
419+
.unwrap_or(false);
420+
421+
if is_file {
422+
let file_path = entry.path();
423+
424+
paths.push(file_path.to_path_buf());
425+
}
426+
}
427+
428+
Ok(paths)
429+
}
430+
383431
async fn create_build_context_archive(
384432
task: task::TaskCtx,
385433
build_path: &Path,
386-
_dockerfile: &Path,
434+
dockerfile: &Path,
387435
) -> Result<Vec<u8>> {
388436
task.log(format!(
389437
"[Remote Build] Creating gzipped tar archive from build path: {:?}",
390438
build_path
391439
));
392440

441+
let dockerfile_path_buf = build_path.join(dockerfile);
442+
let dockerfile = Path::new(&dockerfile_path_buf);
443+
444+
// Get a list of all paths that weren't in .dockerignore
445+
let build_file_paths = prepare_build_context_dir(build_path, dockerfile)?;
446+
393447
// Create a gzipped tar archive of the build context
394448
let mut archive_data = Vec::new();
395449
{
396450
let gz_encoder = GzEncoder::new(&mut archive_data, Compression::default());
397451
let mut tar = tar::Builder::new(gz_encoder);
398452

399-
// Add the entire build directory to the archive
400-
tar.append_dir_all(".", build_path)
401-
.context("Failed to create build context archive")?;
453+
// Add the prepared build file paths to the archive
454+
for file_path in build_file_paths.iter() {
455+
let relative_path = file_path.strip_prefix(build_path)
456+
.context("Failed to strip build path prefix")?;
457+
458+
tar.append_path_with_name(&file_path, relative_path)
459+
.context(format!("Failed to add file to tar: {:?}", file_path))?;
460+
}
402461

403462
tar.finish().context("Failed to finalize tar archive")?;
404463
}

0 commit comments

Comments
 (0)