Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ all-test:
cargo build --release --all-features

install:
install -D -t $(DESTDIR)$(prefix)/bin target/release/bootc
install -D -t $(DESTDIR)$(prefix)/lib/bootc/install lib/src/install/*.toml
install -D -m 0755 -t $(DESTDIR)$(prefix)/bin target/release/bootc
install -D -m 0644 -t $(DESTDIR)$(prefix)/lib/bootc/install lib/src/install/*.toml
if test -d man; then install -D -m 0644 -t $(DESTDIR)$(prefix)/share/man/man8 man/*.8; fi

bin-archive: all
$(MAKE) install DESTDIR=tmp-install && tar --zstd -C tmp-install -cf target/bootc.tar.zst . && rm tmp-install -rf
Expand Down
5 changes: 3 additions & 2 deletions contrib/packaging/bootc.spec
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ Summary: Boot containers

License: ASL 2.0
URL: https://github.com/containers/bootc
Source0: https://github.com/containers/bootc/releases/download/v%{version}/bootc-%{version}.tar.zstd
Source1: https://github.com/containers/bootc/releases/download/v%{version}/bootc-%{version}-vendor.tar.zstd
Source0: https://github.com/containers/bootc/releases/download/v%{version}/bootc-%{version}.tar.zst
Source1: https://github.com/containers/bootc/releases/download/v%{version}/bootc-%{version}-vendor.tar.zst

BuildRequires: make
BuildRequires: openssl-devel
Expand All @@ -29,6 +29,7 @@ BuildRequires: systemd-devel
%doc README.md
%{_bindir}/bootc
%{_prefix}/lib/bootc
%{_mandir}/man8/bootc*

%prep
%autosetup -p1 -Sgit
Expand Down
11 changes: 10 additions & 1 deletion lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,16 @@ pub(crate) enum TestingOpts {
},
}

/// Deploy and upgrade via bootable container images.
/// Deploy and transactionally in-place with bootable container images.
///
/// The `bootc` project currently uses ostree-containers as a backend
/// to support a model of bootable container images. Once installed,
/// whether directly via `bootc install` (executed as part of a container)
/// or via another mechanism such as an OS installer tool, further
/// updates can be pulled via e.g. `bootc upgrade`.
///
/// Changes in `/etc` and `/var` persist.
///
#[derive(Debug, Parser)]
#[clap(name = "bootc")]
#[clap(rename_all = "kebab-case")]
Expand Down
77 changes: 69 additions & 8 deletions xtask/src/xtask.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ fn main() {
#[allow(clippy::type_complexity)]
const TASKS: &[(&str, fn(&Shell) -> Result<()>)] = &[
("vendor", vendor),
("manpages", manpages),
("package", package),
("package-srpm", package_srpm),
("custom-lints", custom_lints),
Expand Down Expand Up @@ -57,15 +58,31 @@ fn gitrev_to_version(v: &str) -> String {

#[context("Finding gitrev")]
fn gitrev(sh: &Shell) -> Result<String> {
if let Ok(rev) = cmd!(sh, "git describe --tags").ignore_stderr().read() {
if let Ok(rev) = cmd!(sh, "git describe --tags --exact-match")
.ignore_stderr()
.read()
{
Ok(gitrev_to_version(&rev))
} else {
let mut desc = cmd!(sh, "git describe --tags --always").read()?;
desc.insert_str(0, "0.");
Ok(desc)
let timestamp = git_timestamp(sh)?;
// We always inject the timestamp first to ensure that newer is better.
Ok(format!("{timestamp}.{desc}"))
}
}

#[context("Manpages")]
fn manpages(sh: &Shell) -> Result<()> {
sh.create_dir("target/man")?;
cmd!(
sh,
"cargo run --features=docgen -- man --directory target/man"
)
.run()?;
Ok(())
}

/// Return a string formatted version of the git commit timestamp, up to the minute
/// but not second because, well, we're not going to build more than once a second.
#[context("Finding git timestamp")]
Expand All @@ -82,14 +99,28 @@ struct Package {
srcpath: Utf8PathBuf,
}

/// Return the timestamp of the latest git commit in seconds since the Unix epoch.
fn git_source_date_epoch(dir: &Utf8Path) -> Result<u64> {
let o = Command::new("git")
.args(["log", "-1", "--pretty=%ct"])
.current_dir(dir)
.output()?;
if !o.status.success() {
anyhow::bail!("git exited with an error: {:?}", o);
}
let buf = String::from_utf8(o.stdout).context("Failed to parse git log output")?;
let r = buf.trim().parse()?;
Ok(r)
}

#[context("Packaging")]
fn impl_package(sh: &Shell) -> Result<Package> {
let source_date_epoch = git_source_date_epoch(".".into())?;
manpages(sh)?;
let v = gitrev(sh)?;
let timestamp = git_timestamp(sh)?;
// We always inject the timestamp first to ensure that newer is better.
let v = format!("{timestamp}.{v}");

let namev = format!("{NAME}-{v}");
let p = Utf8Path::new("target").join(format!("{namev}.tar.zstd"));
let p = Utf8Path::new("target").join(format!("{namev}.tar"));
let o = File::create(&p)?;
let prefix = format!("{namev}/");
let st = Command::new("git")
Expand All @@ -105,9 +136,29 @@ fn impl_package(sh: &Shell) -> Result<Package> {
if !st.success() {
anyhow::bail!("Failed to run {st:?}");
}
let st = Command::new("tar")
.args([
"-r",
"-C",
"target",
"--sort=name",
"--owner=0",
"--group=0",
"--numeric-owner",
"--pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime",
])
.arg(format!("--transform=s,^,{prefix},"))
.arg(format!("--mtime=@{source_date_epoch}"))
.args(["-f", p.as_str(), "man"])
.status()
.context("Failed to execute tar")?;
if !st.success() {
anyhow::bail!("Failed to run {st:?}");
}
cmd!(sh, "zstd -f {p}").run()?;
Ok(Package {
version: v,
srcpath: p,
srcpath: format!("{p}.zst").into(),
})
}

Expand All @@ -118,6 +169,16 @@ fn package(sh: &Shell) -> Result<()> {
}

fn impl_srpm(sh: &Shell) -> Result<Utf8PathBuf> {
{
let _g = sh.push_dir("target");
for name in sh.read_dir(".")? {
if let Some(name) = name.to_str() {
if name.ends_with(".src.rpm") {
sh.remove_path(name)?;
}
}
}
}
let pkg = impl_package(sh)?;
vendor(sh)?;
let td = tempfile::tempdir_in("target").context("Allocating tmpdir")?;
Expand All @@ -126,7 +187,7 @@ fn impl_srpm(sh: &Shell) -> Result<Utf8PathBuf> {
let srcpath = td.join(pkg.srcpath.file_name().unwrap());
std::fs::rename(pkg.srcpath, srcpath)?;
let v = pkg.version;
let vendorpath = td.join(format!("{NAME}-{v}-vendor.tar.zstd"));
let vendorpath = td.join(format!("{NAME}-{v}-vendor.tar.zst"));
std::fs::rename(VENDORPATH, vendorpath)?;
{
let specin = File::open(format!("contrib/packaging/{NAME}.spec"))
Expand Down