Skip to content

Commit

Permalink
Remove use of LXD
Browse files Browse the repository at this point in the history
Having buildchain only operate locally leaves where it actually runs as
a higher-level decision for the project requirements and infrastructure.

e.g.:

- In a VM, using GitHub Actions or GitLab CI
- In a Docker container, using Woodpecker
- On a physical machine, using Jenkins

Signed-off-by: Tim Crawford <tcrawford@system76.com>
  • Loading branch information
crawfxrd committed Sep 27, 2023
1 parent 773c482 commit 8f9c4ad
Show file tree
Hide file tree
Showing 9 changed files with 28 additions and 145 deletions.
11 changes: 0 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ doc = false
[dependencies]
base32 = "0.4.0"
clap = "3.2.25"
lxd = "0.1.9"
plain = "0.2.3"
rand = "0.8.5"
reqwest = { version = "0.11.20", features = ["blocking"] }
Expand Down
1 change: 0 additions & 1 deletion buildchain.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"name": "buildchain",
"base": "ubuntu:16.04",
"prepare": [
["apt-get", "update"],
["apt-get", "dist-upgrade", "-y"],
Expand Down
2 changes: 0 additions & 2 deletions deps.sh

This file was deleted.

1 change: 0 additions & 1 deletion example/buildchain.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"name": "example",
"base": "ubuntu:16.04",
"prepare": [
["echo", "prepare"]
],
Expand Down
138 changes: 26 additions & 112 deletions src/build.rs
Original file line number Diff line number Diff line change
@@ -1,131 +1,53 @@
// SPDX-License-Identifier: GPL-3.0-only

use serde::{Deserialize, Serialize};
use std::fs;
use std::io;
use std::env;
use std::path::Path;
use std::process::Command;

use lxd::{Container, Image, Location};
use tempfile::TempDir;

use crate::{sign_manifest, Config, Sha384, Source, Store};
use crate::{sign_manifest, Config, Source, Store};

/// A temporary structure used to generate a unique build environment
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
struct BuildEnvironmentConfig {
/// The LXC base to use
pub base: String,
/// The commands to run to generate a build environment
pub prepare: Vec<Vec<String>>,
}

fn prepare(config: &Config, location: &Location) -> io::Result<String> {
let build_json = serde_json::to_string(&BuildEnvironmentConfig {
base: config.base.clone(),
prepare: config.prepare.clone(),
})
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;

let build_sha = Sha384::new(&mut build_json.as_bytes())
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;

let build_sha_str = serde_json::to_string(&build_sha)
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;

let container_name = format!("buildchain-{}-prepare", config.name);
let build_image = format!(
"buildchain-{}-{}",
config.name,
build_sha_str.trim_matches('"')
);

if Image::new(location.clone(), &build_image).is_ok() {
println!("Build environment cached as {}", build_image);
} else {
let mut container = if config.privileged {
println!(
"Create privileged container {} from {}",
container_name, &config.base
);
unsafe { Container::new_privileged(location.clone(), &container_name, &config.base)? }
} else {
println!("Create container {} from {}", container_name, &config.base);
Container::new(location.clone(), &container_name, &config.base)?
};

for command in config.prepare.iter() {
let mut args = vec![];
for arg in command.iter() {
args.push(arg.as_str());
}

println!("Prepare command {:?}", args);
container.exec(&args)?;
fn prepare(config: &Config) -> io::Result<()> {
for command in config.prepare.iter() {
let mut args = Vec::new();
for arg in command.iter().skip(1) {
args.push(arg.as_str());
}

println!("Snapshot build environment as {}", build_image);
let snapshot = container.snapshot(&build_image)?;

println!("Publish build environment as {}", build_image);
snapshot.publish(&build_image)?;
println!("Prepare command: {} {:?}", &command[0], args);
Command::new(&command[0]).args(&args).status()?;
}

Ok(build_image)
Ok(())
}

fn run<P: AsRef<Path>, Q: AsRef<Path>>(
config: &Config,
location: &Location,
build_image: &str,
source_path: P,
temp_path: Q,
) -> io::Result<()> {
let source_path = source_path.as_ref();
let temp_path = temp_path.as_ref();

let container_name = format!("buildchain-{}-build", config.name);

let mut container = if config.privileged {
println!(
"Create privileged container {} from {}",
container_name, build_image
);
unsafe { Container::new_privileged(location.clone(), &container_name, build_image)? }
} else {
println!("Create container {} from {}", container_name, build_image);
Container::new(location.clone(), &container_name, build_image)?
};

println!("Push source");
container.push(source_path, "/root", true)?;

fn run(config: &Config) -> io::Result<()> {
for command in config.build.iter() {
let mut args = Vec::new();
for arg in command.iter() {
for arg in command.iter().skip(1) {
args.push(arg.as_str());
}

println!("Build command {:?}", args);
container.exec(&args)?;
println!("Build command: {} {:?}", &command[0], args);
Command::new(&command[0]).args(&args).status()?;
}

println!("Create artifact directory");
container.exec(&["mkdir", "/root/artifacts"])?;
fs::create_dir_all("artifacts")?;

for command in config.publish.iter() {
let mut args = Vec::new();
for arg in command.iter() {
for arg in command.iter().skip(1) {
args.push(arg.as_str());
}

println!("Publish command {:?}", args);
container.exec(&args)?;
println!("Publish command: {} {:?}", &command[0], args);
Command::new(&command[0]).args(&args).status()?;
}

println!("Pull artifacts");
container.pull("/root/artifacts", temp_path, true)?;

Ok(())
}

Expand Down Expand Up @@ -163,7 +85,6 @@ pub struct BuildArguments<'a> {
pub output_path: &'a str,
pub project_name: &'a str,
pub branch_name: &'a str,
pub remote_opt: Option<&'a str>,
pub source_url: &'a str,
pub source_kind: &'a str,
pub use_pihsm: bool,
Expand All @@ -186,23 +107,16 @@ pub fn build(args: BuildArguments) -> io::Result<()> {
let string = fs::read_to_string(source_path.join(config_path))?;
let config = serde_json::from_str::<Config>(&string)?;

let location = if let Some(remote) = args.remote_opt {
println!("buildchain: building {} on {}", config.name, remote);
Location::Remote(remote.to_string())
} else {
println!("buildchain: building {} locally", config.name);
Location::Local
};
println!("buildchain: building {}", config.name);

// Run all commands from the context of the buildroot.
let cwd = env::current_dir()?;
env::set_current_dir(&temp_dir)?;

let build_image = prepare(&config, &location)?;
prepare(&config)?;
run(&config)?;

run(
&config,
&location,
&build_image,
&source_path,
temp_dir.path(),
)?;
env::set_current_dir(cwd)?;

let store = Store::new(&temp_dir);
let manifest = store.import_artifacts(source_time)?;
Expand Down
9 changes: 2 additions & 7 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,10 @@ use serde::{Deserialize, Serialize};
pub struct Config {
/// The name of this build project
pub name: String,
/// The LXC base to use
pub base: String,
/// True if the LXC container for builds should be privileged
#[serde(default = "Default::default")]
pub privileged: bool,
/// The commands to run to generate a build environment
pub prepare: Vec<Vec<String>>,
/// The commands to run that build the artifacts in /root/source
/// The commands to run that build the artifacts in `source/`
pub build: Vec<Vec<String>>,
/// The commands to run that publish the artifacts to /root/artifacts
/// The commands to run that publish the artifacts to `artifacts/`
pub publish: Vec<Vec<String>>,
}
2 changes: 0 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

#![allow(clippy::uninlined_format_args)]

pub use lxd::Location;

pub use crate::block::Block;
pub use crate::build::{build, BuildArguments};
pub use crate::config::Config;
Expand Down
8 changes: 0 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,6 @@ fn buildchain() -> Result<(), String> {
.takes_value(true)
.help("Tail signature branch name"),
)
.arg(
Arg::with_name("remote")
.short('r')
.long("remote")
.takes_value(true)
.help("Remote LXC server"),
)
.arg(
Arg::with_name("source_url")
.takes_value(true)
Expand Down Expand Up @@ -114,7 +107,6 @@ fn buildchain() -> Result<(), String> {
output_path: matches.value_of("output").unwrap_or("buildchain.tar"),
project_name: matches.value_of("project").unwrap_or("default"),
branch_name: matches.value_of("branch").unwrap_or("master"),
remote_opt: matches.value_of("remote"),
source_url: matches.value_of("source_url").unwrap_or("."),
source_kind: matches.value_of("source_kind").unwrap_or("dir"),
use_pihsm: matches.is_present("use_pihsm"),
Expand Down

0 comments on commit 8f9c4ad

Please sign in to comment.