Skip to content

Commit f0dd725

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

File tree

2 files changed

+75
-20
lines changed

2 files changed

+75
-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: 74 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,60 @@ 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
212+
let truncated = if log_content.len() > 50000 {
213+
format!("... (truncated, showing last 50000 bytes) ...\n{}", &log_content[log_content.len() - 50000..])
214+
} else {
215+
log_content
216+
};
217+
writeln!(file, "{truncated}")?;
218+
writeln!(file, "```")?;
219+
writeln!(file, "</details>\n")?;
177220
}
221+
222+
Ok(())
178223
}
179224

180-
fn run_tests(test_case: &str, base_dir: Option<PathBuf>, keep_all: bool) -> anyhow::Result<()> {
225+
fn run_tests(test_case: &str, base_dir: Option<PathBuf>, keep_all: bool, github_summary: bool) -> anyhow::Result<()> {
181226
// Create the base directory - either use provided path or create a temp one
182227
let base_dir = match base_dir {
183228
Some(path) => {
@@ -191,12 +236,10 @@ fn run_tests(test_case: &str, base_dir: Option<PathBuf>, keep_all: bool) -> anyh
191236
}
192237
};
193238

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

197241
if test_case == "all" {
198242
let all_tests = test_cases();
199-
num_tests = all_tests.len();
200243
let max_name_len = all_tests.iter().map(|t| t.name.len()).max().unwrap_or(0);
201244

202245
for TestCase {
@@ -205,11 +248,19 @@ fn run_tests(test_case: &str, base_dir: Option<PathBuf>, keep_all: bool) -> anyh
205248
requires_namespace: _,
206249
} in all_tests
207250
{
208-
num_ok += run_single_test(name, &base_dir, keep_all, max_name_len).context(name)? as usize;
251+
results.push(run_single_test(name, &base_dir, keep_all, max_name_len).context(name)?);
209252
}
210253
} else {
211254
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;
255+
results.push(run_single_test(test_case, &base_dir, keep_all, max_name_len).context(test_case.to_string())?);
256+
}
257+
258+
let num_tests = results.len();
259+
let num_ok = results.iter().filter(|r| r.passed).count();
260+
261+
// Write GitHub Actions summary if requested
262+
if github_summary {
263+
write_github_summary(&results, num_ok, num_tests)?;
213264
}
214265

215266
let num_failures = num_tests - num_ok;
@@ -244,6 +295,9 @@ enum CliCommand {
244295
/// Keep test artifacts even for passing tests (by default only failing tests are kept)
245296
#[arg(long)]
246297
keep_all: bool,
298+
/// Write test results to GitHub Actions job summary ($GITHUB_STEP_SUMMARY)
299+
#[arg(long)]
300+
github_summary: bool,
247301
},
248302
StartVm {
249303
#[arg(long)]
@@ -259,6 +313,7 @@ impl Default for CliCommand {
259313
test_case: "all".to_string(),
260314
base_dir: None,
261315
keep_all: false,
316+
github_summary: false,
262317
}
263318
}
264319
}
@@ -279,6 +334,6 @@ fn main() -> anyhow::Result<()> {
279334
tmp_dir,
280335
requires_namespace: false, // Will be set by start_vm based on test case
281336
}),
282-
CliCommand::Test { test_case, base_dir, keep_all } => run_tests(&test_case, base_dir, keep_all),
337+
CliCommand::Test { test_case, base_dir, keep_all, github_summary } => run_tests(&test_case, base_dir, keep_all, github_summary),
283338
}
284339
}

0 commit comments

Comments
 (0)