-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
switch to fixed directory for twoliter tools #102
Changes from all commits
0edea09
cb1aa17
8419d5c
5490dae
d7aba25
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/.git | ||
/.gomodcache | ||
/build/* | ||
!/build/rpms/ | ||
/build/rpms/* | ||
!/build/rpms/*.rpm | ||
/build/rpms/*-debuginfo-*.rpm | ||
/build/rpms/*-debugsource-*.rpm | ||
!/build/tools/* | ||
**/target/* | ||
/sbkeys | ||
/tests |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,9 +1,10 @@ | ||||||
use crate::cargo_make::CargoMake; | ||||||
use crate::project; | ||||||
use crate::tools::{install_tools, tools_tempdir}; | ||||||
use crate::project::{self}; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
use crate::tools::install_tools; | ||||||
use anyhow::Result; | ||||||
use clap::Parser; | ||||||
use std::path::PathBuf; | ||||||
use tokio::fs; | ||||||
|
||||||
/// Run a cargo make command in Twoliter's build environment. Known Makefile.toml environment | ||||||
/// variables will be passed-through to the cargo make invocation. | ||||||
|
@@ -33,12 +34,13 @@ pub(crate) struct Make { | |||||
impl Make { | ||||||
pub(super) async fn run(&self) -> Result<()> { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ecpullen these are changes to the code that you are moving. |
||||||
let project = project::load_or_find_project(self.project_path.clone()).await?; | ||||||
let tempdir = tools_tempdir()?; | ||||||
install_tools(&tempdir).await?; | ||||||
let makefile_path = tempdir.path().join("Makefile.toml"); | ||||||
let toolsdir = project.project_dir().join("build/tools"); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe the project object should provide such things (build_dir, tools_dir, etc)
Suggested change
|
||||||
fs::remove_dir_all(&toolsdir).await?; | ||||||
install_tools(&toolsdir).await?; | ||||||
let makefile_path = toolsdir.join("Makefile.toml"); | ||||||
CargoMake::new(&project, &self.arch)? | ||||||
.env("CARGO_HOME", self.cargo_home.display().to_string()) | ||||||
.env("TWOLITER_TOOLS_DIR", tempdir.path().display().to_string()) | ||||||
.env("TWOLITER_TOOLS_DIR", toolsdir.display().to_string()) | ||||||
.env("BUILDSYS_VERSION_IMAGE", project.release_version()) | ||||||
.makefile(makefile_path) | ||||||
.project_dir(project.project_dir()) | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,9 @@ | ||
use anyhow::{Context, Result}; | ||
use filetime::{set_file_handle_times, set_file_mtime, FileTime}; | ||
use flate2::read::ZlibDecoder; | ||
use log::debug; | ||
use std::path::Path; | ||
use tar::Archive; | ||
use tempfile::TempDir; | ||
use tokio::fs; | ||
use tokio::io::AsyncWriteExt; | ||
|
||
|
@@ -16,36 +16,38 @@ const PUBSYS_SETUP: &[u8] = include_bytes!(env!("CARGO_BIN_FILE_PUBSYS_SETUP")); | |
const TESTSYS: &[u8] = include_bytes!(env!("CARGO_BIN_FILE_TESTSYS")); | ||
const TUFTOOL: &[u8] = include_bytes!(env!("CARGO_BIN_FILE_TUFTOOL")); | ||
|
||
/// Create a `TempDir` object and provide a tools-centric error message if it fails. Make sure you | ||
/// hang on to the `TempDir` for as long as you need it. It will be deleted when it goes out of | ||
/// scope. | ||
pub(crate) fn tools_tempdir() -> Result<TempDir> { | ||
TempDir::new().context("Unable to create a tempdir for Twoliter's tools") | ||
} | ||
|
||
/// Install tools into the given `tools_dir`. If you use a `TempDir` object, make sure to pass it by | ||
/// reference and hold on to it until you no longer need the tools to still be installed (it will | ||
/// auto delete when it goes out of scope). | ||
pub(crate) async fn install_tools(tools_dir: impl AsRef<Path>) -> Result<()> { | ||
let dir = tools_dir.as_ref(); | ||
debug!("Installing tools to '{}'", dir.display()); | ||
|
||
write_bin("bottlerocket-variant", BOTTLEROCKET_VARIANT, &dir).await?; | ||
write_bin("buildsys", BUILDSYS, &dir).await?; | ||
write_bin("pubsys", PUBSYS, &dir).await?; | ||
write_bin("pubsys-setup", PUBSYS_SETUP, &dir).await?; | ||
write_bin("testsys", TESTSYS, &dir).await?; | ||
write_bin("tuftool", TUFTOOL, &dir).await?; | ||
|
||
// Write out the embedded tools and scripts. | ||
unpack_tarball(&dir) | ||
.await | ||
.context("Unable to install tools")?; | ||
|
||
// Pick one of the embedded files for use as the canonical mtime. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need a canonical mtime? Is this preventing docker rebuilds? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'll add a comment to the code. It's a minor optimization to make the build context more efficient by not always copying the tools through. For example on a local build with a 180 MiB file:
The build context is more intelligent than a Docker layer in the sense that modifying a single file results in only that file being transferred, not the entire build context. But it still seems worth avoiding unnecessary copies. The direction I'm exploring with passing file descriptors could let us get rid of all the changes to the build context. |
||
let metadata = fs::metadata(dir.join("Dockerfile")) | ||
.await | ||
.context("Unable to get Dockerfile metadata")?; | ||
let mtime = FileTime::from_last_modification_time(&metadata); | ||
|
||
write_bin("bottlerocket-variant", BOTTLEROCKET_VARIANT, &dir, mtime).await?; | ||
write_bin("buildsys", BUILDSYS, &dir, mtime).await?; | ||
write_bin("pubsys", PUBSYS, &dir, mtime).await?; | ||
write_bin("pubsys-setup", PUBSYS_SETUP, &dir, mtime).await?; | ||
write_bin("testsys", TESTSYS, &dir, mtime).await?; | ||
write_bin("tuftool", TUFTOOL, &dir, mtime).await?; | ||
|
||
// Apply the mtime to the directory now that the writes are done. | ||
set_file_mtime(dir, mtime).context(format!("Unable to set mtime for '{}'", dir.display()))?; | ||
|
||
Ok(()) | ||
} | ||
|
||
async fn write_bin(name: &str, data: &[u8], dir: impl AsRef<Path>) -> Result<()> { | ||
async fn write_bin(name: &str, data: &[u8], dir: impl AsRef<Path>, mtime: FileTime) -> Result<()> { | ||
let path = dir.as_ref().join(name); | ||
let mut f = fs::OpenOptions::new() | ||
.create(true) | ||
|
@@ -60,7 +62,12 @@ async fn write_bin(name: &str, data: &[u8], dir: impl AsRef<Path>) -> Result<()> | |
.context(format!("Unable to write to '{}'", path.display()))?; | ||
f.flush() | ||
.await | ||
.context(format!("Unable to finalize '{}'", path.display())) | ||
.context(format!("Unable to finalize '{}'", path.display()))?; | ||
|
||
let f = f.into_std().await; | ||
set_file_handle_times(&f, None, Some(mtime)) | ||
.context(format!("Unable to set mtime for '{}'", path.display()))?; | ||
Ok(()) | ||
} | ||
|
||
async fn unpack_tarball(tools_dir: impl AsRef<Path>) -> Result<()> { | ||
|
@@ -77,7 +84,7 @@ async fn unpack_tarball(tools_dir: impl AsRef<Path>) -> Result<()> { | |
|
||
#[tokio::test] | ||
async fn test_install_tools() { | ||
let tempdir = tools_tempdir().unwrap(); | ||
let tempdir = tempfile::TempDir::new().unwrap(); | ||
install_tools(&tempdir).await.unwrap(); | ||
|
||
// Assert that the expected files exist in the tools directory. | ||
|
@@ -98,4 +105,14 @@ async fn test_install_tools() { | |
assert!(tempdir.path().join("pubsys-setup").is_file()); | ||
assert!(tempdir.path().join("testsys").is_file()); | ||
assert!(tempdir.path().join("tuftool").is_file()); | ||
|
||
// Check that the mtimes match. | ||
let dockerfile_metadata = fs::metadata(tempdir.path().join("Dockerfile")) | ||
.await | ||
.unwrap(); | ||
let buildsys_metadata = fs::metadata(tempdir.path().join("buildsys")).await.unwrap(); | ||
let dockerfile_mtime = FileTime::from_last_modification_time(&dockerfile_metadata); | ||
let buildsys_mtime = FileTime::from_last_modification_time(&buildsys_metadata); | ||
|
||
assert_eq!(dockerfile_mtime, buildsys_mtime); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we can avoid updating build.rs, that would be great. The entire file will be changed in an upcoming pr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The addition of a file appears to be necessary for this PR, that is
Dockerfile.dockerignore
, so at least one change inbuild.rs
is not optional. Anyway, the changes here should be easy to replay. Delete the prep dir and add a file.