From 6f0ebf6dc8e2645b8f8bdf7b62cd9600c5760f6d Mon Sep 17 00:00:00 2001 From: "Sean P. Kelly" Date: Wed, 17 Jul 2024 00:19:26 +0000 Subject: [PATCH] add integration test for `twoliter update` --- .github/actions/install-crane/action.yaml | 45 +++++++++++ .github/workflows/release.yml | 4 + .github/workflows/rust.yml | 4 + Cargo.lock | 8 ++ Cargo.toml | 2 + Makefile | 6 +- tests/integration-tests/Cargo.toml | 9 +++ tests/integration-tests/src/lib.rs | 44 +++++++++++ .../integration-tests/src/twoliter_update.rs | 76 +++++++++++++++++++ tests/projects/external-kit/Twoliter.toml | 10 +-- 10 files changed, 199 insertions(+), 9 deletions(-) create mode 100644 .github/actions/install-crane/action.yaml create mode 100644 tests/integration-tests/Cargo.toml create mode 100644 tests/integration-tests/src/lib.rs create mode 100644 tests/integration-tests/src/twoliter_update.rs diff --git a/.github/actions/install-crane/action.yaml b/.github/actions/install-crane/action.yaml new file mode 100644 index 000000000..194fcb7d7 --- /dev/null +++ b/.github/actions/install-crane/action.yaml @@ -0,0 +1,45 @@ +name: "Install crane" +description: "Installs crane for use in testing." +inputs: + crane-version: + description: "Version of crane to install" + required: false + default: latest + install-dir: + description: "Directory to install crane" + required: false + default: $HOME/.crane + +runs: + using: "composite" + steps: + - shell: bash + run: | + mkdir -p ${{ inputs.install-dir }} + + VERSION=${{ inputs.crane-version }} + if [[ "${VERSION}" == "latest" ]]; then + VERSION=$(gh release list \ + --exclude-pre-releases \ + -R google/go-containerregistry \ + --json name \ + | jq -r '.[0].name') + fi + + case ${{ runner.arch }} in + X64) + ARCH=x86_64 + ;; + ARM64) + ARCH=arm64 + ;; + esac + + ARTIFACT_NAME="go-containerregistry_Linux_${ARCH}.tar.gz" + gh release download "${VERSION}" \ + -R google/go-containerregistry \ + -p "${ARTIFACT_NAME}" \ + --output - \ + | tar -zxvf - -C "${{ inputs.install-dir }}" crane + + echo "${{ inputs.install-dir }}" >> "${GITHUB_PATH}" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7f0de063c..8f853bdcf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -58,6 +58,10 @@ jobs: - uses: actions/checkout@v3 with: submodules: recursive + - name: Install crane for testing + uses: ./.github/actions/install-crane + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Install cargo-dist run: | cargo install --locked \ diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index e784ba945..28cd6e062 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -22,6 +22,10 @@ jobs: labels: bottlerocket_ubuntu-latest_16-core steps: - uses: actions/checkout@v3 + - name: Install crane for testing + uses: ./.github/actions/install-crane + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: cargo install cargo-deny --locked - run: cargo install cargo-make --locked - run: make build diff --git a/Cargo.lock b/Cargo.lock index 17dc5cc8c..48e551449 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1833,6 +1833,14 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "integration-tests" +version = "0.1.0" +dependencies = [ + "tokio", + "twoliter", +] + [[package]] name = "ipnet" version = "2.9.0" diff --git a/Cargo.toml b/Cargo.toml index 30bc80d18..a0a22017f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,8 @@ members = [ "tools/unplug", "tools/update-metadata", "twoliter", + + "tests/integration-tests", ] [profile.release] diff --git a/Makefile b/Makefile index d078a6521..b1f5c5c35 100644 --- a/Makefile +++ b/Makefile @@ -21,8 +21,12 @@ fmt: test: cargo test --release --locked +.PHONY: integ +integ: + cargo test --manifest-path tests/integration-tests/Cargo.toml -- --include-ignored + .PHONY: check -check: fmt clippy deny test +check: fmt clippy deny test integ .PHONY: build build: check diff --git a/tests/integration-tests/Cargo.toml b/tests/integration-tests/Cargo.toml new file mode 100644 index 000000000..869c25288 --- /dev/null +++ b/tests/integration-tests/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "integration-tests" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" + +[dev-dependencies] +tokio = { version = "1", default-features = false, features = ["process", "fs", "rt-multi-thread"] } +twoliter = { version = "0", path = "../../twoliter", artifact = [ "bin:twoliter" ] } diff --git a/tests/integration-tests/src/lib.rs b/tests/integration-tests/src/lib.rs new file mode 100644 index 000000000..379a7b0f2 --- /dev/null +++ b/tests/integration-tests/src/lib.rs @@ -0,0 +1,44 @@ +#![cfg(test)] + +use std::ffi::OsStr; +use std::path::PathBuf; +use tokio::process::Command; + +mod twoliter_update; + +pub const TWOLITER_PATH: &'static str = env!("CARGO_BIN_FILE_TWOLITER"); + +pub fn test_projects_dir() -> PathBuf { + let mut p = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + p.pop(); + p.join("projects") +} + +pub async fn run_command(cmd: S, args: I, env: E) -> std::process::Output +where + I: IntoIterator, + E: IntoIterator, + S: AsRef, +{ + let args: Vec = args.into_iter().collect(); + + println!( + "Executing '{}' with args [{}]", + cmd.as_ref().to_string_lossy(), + args.iter() + .map(|arg| format!("'{}'", arg.as_ref().to_string_lossy())) + .collect::>() + .join(", ") + ); + + let output = Command::new(cmd) + .args(args.into_iter()) + .envs(env.into_iter()) + .output() + .await + .expect("failed to execute process"); + + println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); + output +} diff --git a/tests/integration-tests/src/twoliter_update.rs b/tests/integration-tests/src/twoliter_update.rs new file mode 100644 index 000000000..a565aa5cf --- /dev/null +++ b/tests/integration-tests/src/twoliter_update.rs @@ -0,0 +1,76 @@ +use super::{run_command, test_projects_dir, TWOLITER_PATH}; + +const EXPECTED_LOCKFILE: &str = r#"schema-version = 1 +release-version = "1.0.0" +digest = "m/6DbBacnIBHMo34GCuzA4pAHzrnQJ2G/XJMMguZXjw=" + +[sdk] +name = "bottlerocket-sdk" +version = "0.42.0" +vendor = "bottlerocket" +source = "public.ecr.aws/bottlerocket/bottlerocket-sdk:v0.42.0" +digest = "myHHKE41h9qfeyR6V6HB0BfiLPwj3QEFLUFy4TXcR10=" + +[[kit]] +name = "bottlerocket-core-kit" +version = "2.0.0" +vendor = "custom-vendor" +source = "public.ecr.aws/bottlerocket/bottlerocket-core-kit:v2.0.0" +digest = "vlTsAAbSCzXFZofVmw8pLLkRjnG/y8mtb2QsQBSz1zk=" +"#; + +#[tokio::test] +#[ignore] +/// Generates a Twoliter.lock file for the `external-kit` project using docker +async fn test_twoliter_update_docker() { + let external_kit = test_projects_dir().join("external-kit"); + + let lockfile = external_kit.join("Twoliter.lock"); + tokio::fs::remove_file(&lockfile).await.ok(); + + let output = run_command( + TWOLITER_PATH, + [ + "update", + "--project-path", + external_kit.join("Twoliter.toml").to_str().unwrap(), + ], + [("TWOLITER_KIT_IMAGE_TOOL", "docker")], + ) + .await; + + assert!(output.status.success()); + + let lock_contents = tokio::fs::read_to_string(&lockfile).await.unwrap(); + assert_eq!(lock_contents, EXPECTED_LOCKFILE); + + tokio::fs::remove_file(&lockfile).await.ok(); +} + +#[tokio::test] +#[ignore] +/// Generates a Twoliter.lock file for the `external-kit` project using crane +async fn test_twoliter_update_crane() { + let external_kit = test_projects_dir().join("external-kit"); + + let lockfile = external_kit.join("Twoliter.lock"); + tokio::fs::remove_file(&lockfile).await.ok(); + + let output = run_command( + TWOLITER_PATH, + [ + "update", + "--project-path", + external_kit.join("Twoliter.toml").to_str().unwrap(), + ], + [("TWOLITER_KIT_IMAGE_TOOL", "crane")], + ) + .await; + + assert!(output.status.success()); + + let lock_contents = tokio::fs::read_to_string(&lockfile).await.unwrap(); + assert_eq!(lock_contents, EXPECTED_LOCKFILE); + + tokio::fs::remove_file(&lockfile).await.ok(); +} diff --git a/tests/projects/external-kit/Twoliter.toml b/tests/projects/external-kit/Twoliter.toml index 851923590..ea47adb8d 100644 --- a/tests/projects/external-kit/Twoliter.toml +++ b/tests/projects/external-kit/Twoliter.toml @@ -1,19 +1,13 @@ schema-version = 1 release-version = "1.0.0" -[sdk] -name = "bottlerocket-sdk" -vendor = "bottlerocket" -version = "0.41.0" - [vendor.bottlerocket] registry = "public.ecr.aws/bottlerocket" [vendor.custom-vendor] -# We need to figure out how we can do integration testing with this registry = "public.ecr.aws/bottlerocket" [[kit]] -name = "core-kit" -version = "0.1.0" +name = "bottlerocket-core-kit" +version = "2.0.0" vendor = "custom-vendor"