Report missing Docker clearly and preserve CI attempt setup
Some checks failed
Build, test and publish / verify (push) Failing after 3m9s
Some checks failed
Build, test and publish / verify (push) Failing after 3m9s
This commit is contained in:
@@ -25,7 +25,7 @@ public class Ci {
|
|||||||
Path file = Path.of(Setup.required(env, "GITHUB_ENV"));
|
Path file = Path.of(Setup.required(env, "GITHUB_ENV"));
|
||||||
String id = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSSSSSSSS")
|
String id = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSSSSSSSS")
|
||||||
.withZone(ZoneOffset.UTC).format(Instant.now());
|
.withZone(ZoneOffset.UTC).format(Instant.now());
|
||||||
Files.writeString(file, "CI_RUN_ATTEMPT=" + id + "\n", StandardOpenOption.APPEND);
|
Files.writeString(file, "CI_RUN_ATTEMPT=" + id + "\n", StandardOpenOption.CREATE, StandardOpenOption.APPEND);
|
||||||
}
|
}
|
||||||
case "configure-gitea" -> Setup.configureGitea(env);
|
case "configure-gitea" -> Setup.configureGitea(env);
|
||||||
case "configure-docker" -> {
|
case "configure-docker" -> {
|
||||||
|
|||||||
@@ -82,6 +82,14 @@ class CiTests {
|
|||||||
test("Older commit cannot move main", () -> {
|
test("Older commit cannot move main", () -> {
|
||||||
try (Fixture f = new Fixture()) { f.fake.head = "c".repeat(40); f.pipeline.publish(); equal(2L,f.calls("push")); }
|
try (Fixture f = new Fixture()) { f.fake.head = "c".repeat(40); f.pipeline.publish(); equal(2L,f.calls("push")); }
|
||||||
});
|
});
|
||||||
|
test("Unavailable Docker fails before build with a concrete cause", () -> {
|
||||||
|
try (Fixture f = new Fixture()) {
|
||||||
|
f.fake.dockerAvailable = false;
|
||||||
|
try { f.pipeline.verify(); throw new AssertionError("Expected failure"); }
|
||||||
|
catch (IllegalArgumentException error) { equal(true,error.getMessage().contains("Docker is unavailable")); }
|
||||||
|
equal(0L,f.fake.calls.stream().filter(a -> a.getFirst().equals("mvn")).count());
|
||||||
|
}
|
||||||
|
});
|
||||||
test("Architecture mismatch blocks publication", () -> {
|
test("Architecture mismatch blocks publication", () -> {
|
||||||
try (Fixture f = new Fixture()) { f.pipeline.env.put("TARGET_PLATFORM","linux/arm64"); failure(f.pipeline::publish); equal(0L,f.calls("push")); }
|
try (Fixture f = new Fixture()) { f.pipeline.env.put("TARGET_PLATFORM","linux/arm64"); failure(f.pipeline::publish); equal(0L,f.calls("push")); }
|
||||||
});
|
});
|
||||||
@@ -128,6 +136,7 @@ class CiTests {
|
|||||||
final Map<String,String> images = new HashMap<>(), tags = new HashMap<>();
|
final Map<String,String> images = new HashMap<>(), tags = new HashMap<>();
|
||||||
String head = SHA, pushFailure = "", pullFailure = "";
|
String head = SHA, pushFailure = "", pullFailure = "";
|
||||||
boolean manifestError, mavenFailure;
|
boolean manifestError, mavenFailure;
|
||||||
|
boolean dockerAvailable = true;
|
||||||
FakeCommands() { super(Duration.ofMinutes(1)); }
|
FakeCommands() { super(Duration.ofMinutes(1)); }
|
||||||
@Override Result execute(List<String> args, Path cwd, Map<String,String> env, String input, boolean echo) {
|
@Override Result execute(List<String> args, Path cwd, Map<String,String> env, String input, boolean echo) {
|
||||||
calls.add(List.copyOf(args));
|
calls.add(List.copyOf(args));
|
||||||
@@ -135,7 +144,7 @@ class CiTests {
|
|||||||
if (args.getFirst().equals("mvn") && mavenFailure) return new Result(42,"deliberate failure");
|
if (args.getFirst().equals("mvn") && mavenFailure) return new Result(42,"deliberate failure");
|
||||||
if (!args.getFirst().equals("docker")) return new Result(0,"");
|
if (!args.getFirst().equals("docker")) return new Result(0,"");
|
||||||
String command = args.get(1), ref = args.getLast();
|
String command = args.get(1), ref = args.getLast();
|
||||||
if (command.equals("info")) return new Result(0,args.contains("{{.Architecture}}") ? "amd64" : "linux");
|
if (command.equals("info")) return new Result(dockerAvailable ? 0 : 1,args.contains("{{.Architecture}}") ? "amd64" : "linux");
|
||||||
if (command.equals("context")) return new Result(0,"unix:///tmp/test-docker.sock");
|
if (command.equals("context")) return new Result(0,"unix:///tmp/test-docker.sock");
|
||||||
if (command.equals("manifest")) {
|
if (command.equals("manifest")) {
|
||||||
if (manifestError) return new Result(1,"unauthorized");
|
if (manifestError) return new Result(1,"unauthorized");
|
||||||
|
|||||||
@@ -40,7 +40,9 @@ class Pipeline {
|
|||||||
void run(String... args) throws Exception { result(true, args).checked(); }
|
void run(String... args) throws Exception { result(true, args).checked(); }
|
||||||
void requirePlatform() throws Exception {
|
void requirePlatform() throws Exception {
|
||||||
String target = Setup.required(env,"TARGET_PLATFORM");
|
String target = Setup.required(env,"TARGET_PLATFORM");
|
||||||
String arch = capture("docker", "info", "--format", "{{.Architecture}}");
|
var docker = result(false,"docker", "info", "--format", "{{.Architecture}}");
|
||||||
|
check(docker.code() == 0, "Docker is unavailable; start Docker Desktop before running CI (details in verify.log)");
|
||||||
|
String arch = docker.output().strip();
|
||||||
arch = switch (arch) { case "x86_64" -> "amd64"; case "aarch64" -> "arm64"; default -> arch; };
|
arch = switch (arch) { case "x86_64" -> "amd64"; case "aarch64" -> "arm64"; default -> arch; };
|
||||||
String nativePlatform = capture("docker", "info", "--format", "{{.OSType}}") + "/" + arch;
|
String nativePlatform = capture("docker", "info", "--format", "{{.OSType}}") + "/" + arch;
|
||||||
check(target.equals(nativePlatform), "Target " + target + " differs from Docker host " + nativePlatform);
|
check(target.equals(nativePlatform), "Target " + target + " differs from Docker host " + nativePlatform);
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ only then can real main publication/pullback/rerun acceptance be completed.
|
|||||||
|
|
||||||
CI orchestration, setup and behavior tests now run through `java ci/Ci.java`.
|
CI orchestration, setup and behavior tests now run through `java ci/Ci.java`.
|
||||||
The shell/Python helpers have been removed. The source launcher compiles helper
|
The shell/Python helpers have been removed. The source launcher compiles helper
|
||||||
classes in memory without external dependencies or preview flags. Fourteen Java
|
classes in memory without external dependencies or preview flags. Fifteen Java
|
||||||
behavior tests pass, including JSON/configuration preservation, publication gates,
|
behavior tests pass, including JSON/configuration preservation, publication gates,
|
||||||
partial recovery and process deadlines. A real feature run validates this revision
|
partial recovery and process deadlines. A real feature run validates this revision
|
||||||
before updating the existing open PR; no merge to main is authorized.
|
before updating the existing open PR; no merge to main is authorized.
|
||||||
|
|||||||
Reference in New Issue
Block a user