Skip to content

Commit a3326ea

Browse files
committed
WIP pretty github summary?
Signed-off-by: Matej Hrica <[email protected]>
1 parent 7774ff9 commit a3326ea

File tree

2 files changed

+76
-20
lines changed

2 files changed

+76
-20
lines changed

.github/workflows/integration_tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ jobs:
5252
run: curl -L -o /tmp/libkrunfw-5.0.0-x86_64.tgz https://github.com/containers/libkrunfw/releases/download/v5.0.0/libkrunfw-5.0.0-x86_64.tgz && mkdir tmp && tar xf /tmp/libkrunfw-5.0.0-x86_64.tgz -C tmp && sudo mv tmp/lib64/* /lib/x86_64-linux-gnu
5353

5454
- name: Integration tests
55-
run: KRUN_ENOMEM_WORKAROUND=1 KRUN_NO_UNSHARE=1 KRUN_TEST_BASE_DIR=/tmp/libkrun-tests make test TEST_FLAGS="--keep-all"
55+
run: KRUN_ENOMEM_WORKAROUND=1 KRUN_NO_UNSHARE=1 KRUN_TEST_BASE_DIR=/tmp/libkrun-tests make test TEST_FLAGS="--keep-all --github-summary"
5656

5757
- name: Upload test logs
5858
if: always()

tests/runner/src/main.rs

Lines changed: 75 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,20 @@ use anyhow::Context;
22
use clap::Parser;
33
use nix::sys::resource::{getrlimit, setrlimit, Resource};
44
use std::fs::{self, File};
5+
use std::io::Write;
56
use std::panic::catch_unwind;
67
use std::path::{Path, PathBuf};
78
use std::process::{Command, Stdio};
89
use std::env;
910
use tempdir::TempDir;
1011
use test_cases::{test_cases, Test, TestCase, TestSetup};
1112

13+
struct TestResult {
14+
name: String,
15+
passed: bool,
16+
log_path: PathBuf,
17+
}
18+
1219
fn get_test(name: &str) -> anyhow::Result<Box<dyn Test>> {
1320
let tests = test_cases();
1421
tests
@@ -133,7 +140,7 @@ fn setup_namespace_and_run(test_setup: TestSetup) -> anyhow::Result<()> {
133140
}
134141
}
135142

136-
fn run_single_test(test_case: &str, base_dir: &Path, keep_all: bool, max_name_len: usize) -> anyhow::Result<bool> {
143+
fn run_single_test(test_case: &str, base_dir: &Path, keep_all: bool, max_name_len: usize) -> anyhow::Result<TestResult> {
137144
let executable = env::current_exe().context("Failed to detect current executable")?;
138145
let test_dir = base_dir.join(test_case);
139146
fs::create_dir(&test_dir).context("Failed to create test directory")?;
@@ -162,22 +169,61 @@ fn run_single_test(test_case: &str, base_dir: &Path, keep_all: bool, max_name_le
162169
test.check(child);
163170
});
164171

165-
match result {
166-
Ok(()) => {
167-
eprintln!(" OK");
168-
if !keep_all {
169-
let _ = fs::remove_dir_all(&test_dir);
170-
}
171-
Ok(true)
172-
}
173-
Err(_e) => {
174-
eprintln!(" FAIL");
175-
Ok(false)
172+
let passed = result.is_ok();
173+
if passed {
174+
eprintln!("OK");
175+
if !keep_all {
176+
let _ = fs::remove_dir_all(&test_dir);
176177
}
178+
} else {
179+
eprintln!("FAIL");
180+
}
181+
182+
Ok(TestResult {
183+
name: test_case.to_string(),
184+
passed,
185+
log_path,
186+
})
187+
}
188+
189+
fn write_github_summary(results: &[TestResult], num_ok: usize, num_tests: usize) -> anyhow::Result<()> {
190+
let summary_path = env::var("GITHUB_STEP_SUMMARY")
191+
.context("GITHUB_STEP_SUMMARY environment variable not set")?;
192+
193+
let mut file = fs::OpenOptions::new()
194+
.create(true)
195+
.append(true)
196+
.open(&summary_path)
197+
.context("Failed to open GITHUB_STEP_SUMMARY")?;
198+
199+
let all_passed = num_ok == num_tests;
200+
let status = if all_passed { "✅" } else { "❌" };
201+
202+
writeln!(file, "## {status} Integration Tests ({num_ok}/{num_tests} passed)\n")?;
203+
204+
for result in results {
205+
let icon = if result.passed { "✅" } else { "❌" };
206+
let log_content = fs::read_to_string(&result.log_path).unwrap_or_default();
207+
208+
writeln!(file, "<details>")?;
209+
writeln!(file, "<summary>{icon} {}</summary>\n", result.name)?;
210+
writeln!(file, "```")?;
211+
// Limit log size to avoid huge summaries (1 MiB limit)
212+
const MAX_LOG_SIZE: usize = 1024 * 1024;
213+
let truncated = if log_content.len() > MAX_LOG_SIZE {
214+
format!("... (truncated, showing last 1 MiB) ...\n{}", &log_content[log_content.len() - MAX_LOG_SIZE..])
215+
} else {
216+
log_content
217+
};
218+
writeln!(file, "{truncated}")?;
219+
writeln!(file, "```")?;
220+
writeln!(file, "</details>\n")?;
177221
}
222+
223+
Ok(())
178224
}
179225

180-
fn run_tests(test_case: &str, base_dir: Option<PathBuf>, keep_all: bool) -> anyhow::Result<()> {
226+
fn run_tests(test_case: &str, base_dir: Option<PathBuf>, keep_all: bool, github_summary: bool) -> anyhow::Result<()> {
181227
// Create the base directory - either use provided path or create a temp one
182228
let base_dir = match base_dir {
183229
Some(path) => {
@@ -191,12 +237,10 @@ fn run_tests(test_case: &str, base_dir: Option<PathBuf>, keep_all: bool) -> anyh
191237
}
192238
};
193239

194-
let mut num_tests = 1;
195-
let mut num_ok: usize = 0;
240+
let mut results: Vec<TestResult> = Vec::new();
196241

197242
if test_case == "all" {
198243
let all_tests = test_cases();
199-
num_tests = all_tests.len();
200244
let max_name_len = all_tests.iter().map(|t| t.name.len()).max().unwrap_or(0);
201245

202246
for TestCase {
@@ -205,11 +249,19 @@ fn run_tests(test_case: &str, base_dir: Option<PathBuf>, keep_all: bool) -> anyh
205249
requires_namespace: _,
206250
} in all_tests
207251
{
208-
num_ok += run_single_test(name, &base_dir, keep_all, max_name_len).context(name)? as usize;
252+
results.push(run_single_test(name, &base_dir, keep_all, max_name_len).context(name)?);
209253
}
210254
} else {
211255
let max_name_len = test_case.len();
212-
num_ok += run_single_test(test_case, &base_dir, keep_all, max_name_len).context(test_case.to_string())? as usize;
256+
results.push(run_single_test(test_case, &base_dir, keep_all, max_name_len).context(test_case.to_string())?);
257+
}
258+
259+
let num_tests = results.len();
260+
let num_ok = results.iter().filter(|r| r.passed).count();
261+
262+
// Write GitHub Actions summary if requested
263+
if github_summary {
264+
write_github_summary(&results, num_ok, num_tests)?;
213265
}
214266

215267
let num_failures = num_tests - num_ok;
@@ -244,6 +296,9 @@ enum CliCommand {
244296
/// Keep test artifacts even for passing tests (by default only failing tests are kept)
245297
#[arg(long)]
246298
keep_all: bool,
299+
/// Write test results to GitHub Actions job summary ($GITHUB_STEP_SUMMARY)
300+
#[arg(long)]
301+
github_summary: bool,
247302
},
248303
StartVm {
249304
#[arg(long)]
@@ -259,6 +314,7 @@ impl Default for CliCommand {
259314
test_case: "all".to_string(),
260315
base_dir: None,
261316
keep_all: false,
317+
github_summary: false,
262318
}
263319
}
264320
}
@@ -279,6 +335,6 @@ fn main() -> anyhow::Result<()> {
279335
tmp_dir,
280336
requires_namespace: false, // Will be set by start_vm based on test case
281337
}),
282-
CliCommand::Test { test_case, base_dir, keep_all } => run_tests(&test_case, base_dir, keep_all),
338+
CliCommand::Test { test_case, base_dir, keep_all, github_summary } => run_tests(&test_case, base_dir, keep_all, github_summary),
283339
}
284340
}

0 commit comments

Comments
 (0)