From a44d227a788f75fdf2ecf85efbd4cb8b4117a4de Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Fri, 24 Jul 2020 09:41:04 +0200 Subject: [PATCH 01/13] [JENKINS-62014] Add support for global build step env var filters --- .mvn/maven.config | 1 + pom.xml | 4 ++-- .../plugins/workflow/steps/durable_task/DurableTaskStep.java | 5 ++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.mvn/maven.config b/.mvn/maven.config index 2a0299c4..66d406fe 100644 --- a/.mvn/maven.config +++ b/.mvn/maven.config @@ -1,2 +1,3 @@ -Pconsume-incrementals -Pmight-produce-incrementals +-Duse-jenkins-bom diff --git a/pom.xml b/pom.xml index f98eab59..e42ded9c 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ org.jenkins-ci.plugins plugin - 3.54 + 4.4 org.jenkins-ci.plugins.workflow @@ -64,7 +64,7 @@ 2.36 -SNAPSHOT - 2.176.1 + 2.248 8 true 2.20 diff --git a/src/main/java/org/jenkinsci/plugins/workflow/steps/durable_task/DurableTaskStep.java b/src/main/java/org/jenkinsci/plugins/workflow/steps/durable_task/DurableTaskStep.java index 061b1bac..b33d543e 100644 --- a/src/main/java/org/jenkinsci/plugins/workflow/steps/durable_task/DurableTaskStep.java +++ b/src/main/java/org/jenkinsci/plugins/workflow/steps/durable_task/DurableTaskStep.java @@ -35,6 +35,7 @@ import hudson.init.Terminator; import hudson.model.Node; import hudson.model.Result; +import hudson.model.Run; import hudson.model.TaskListener; import hudson.remoting.Channel; import hudson.remoting.ChannelClosedException; @@ -61,6 +62,7 @@ import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import jenkins.model.Jenkins; +import jenkins.tasks.filters.EnvVarsFilterableBuilder; import jenkins.util.Timer; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; @@ -96,7 +98,7 @@ * When the process exits, the status code is also written to a file and ultimately results in the step passing or failing. *

Tasks can also be run on the master node, which differs only in that there is no possibility of a network failure. */ -public abstract class DurableTaskStep extends Step { +public abstract class DurableTaskStep extends Step implements EnvVarsFilterableBuilder { private static final Logger LOGGER = Logger.getLogger(DurableTaskStep.class.getName()); @@ -312,6 +314,7 @@ static final class Execution extends AbstractStepExecutionImpl implements Runnab durableTask.defaultCharset(); } Launcher launcher = context.get(Launcher.class); + launcher.prepareFilterRules(context.get(Run.class), step); LOGGER.log(Level.FINE, "launching task against {0} using {1}", new Object[] {ws.getChannel(), launcher}); try { controller = durableTask.launch(context.get(EnvVars.class), ws, launcher, listener); From 3337702830c2780ce3aeccd7050aa9c53cb13cf3 Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Mon, 27 Jul 2020 14:14:27 +0200 Subject: [PATCH 02/13] Fix SpotBugs issues --- .../workflow/support/steps/ExecutorStepExecution.java | 5 +++-- .../workflow/support/steps/WorkspaceStepExecution.java | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepExecution.java b/src/main/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepExecution.java index 39268967..885b96b2 100644 --- a/src/main/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepExecution.java +++ b/src/main/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepExecution.java @@ -836,8 +836,9 @@ private final class PlaceholderExecutable implements ContinuableExecutable, Acce FilePath workspace = lease.path; // Cf. AbstractBuild.getEnvironment: env.put("WORKSPACE", workspace.getRemote()); - if (workspace.getParent() != null) { - env.put("WORKSPACE_TMP", WorkspaceList.tempDir(workspace).getRemote()); // JENKINS-60634 + final FilePath tempDir = WorkspaceList.tempDir(workspace); + if (tempDir != null) { + env.put("WORKSPACE_TMP", tempDir.getRemote()); // JENKINS-60634 } FlowNode flowNode = context.get(FlowNode.class); if (flowNode != null) { diff --git a/src/main/java/org/jenkinsci/plugins/workflow/support/steps/WorkspaceStepExecution.java b/src/main/java/org/jenkinsci/plugins/workflow/support/steps/WorkspaceStepExecution.java index ccfdf10c..2d2ca789 100644 --- a/src/main/java/org/jenkinsci/plugins/workflow/support/steps/WorkspaceStepExecution.java +++ b/src/main/java/org/jenkinsci/plugins/workflow/support/steps/WorkspaceStepExecution.java @@ -62,8 +62,9 @@ public boolean start() throws Exception { getContext().get(TaskListener.class).getLogger().println("Running in " + workspace); Map env = new HashMap<>(); env.put("WORKSPACE", workspace.getRemote()); - if (workspace.getParent() != null) { - env.put("WORKSPACE_TMP", WorkspaceList.tempDir(workspace).getRemote()); + final FilePath tempDir = WorkspaceList.tempDir(workspace); + if (tempDir != null) { + env.put("WORKSPACE_TMP", tempDir.getRemote()); } getContext().newBodyInvoker() .withContexts( From 9731ae7b277fee0a63af07d025b799bcf5968388 Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Wed, 12 Aug 2020 09:00:23 +0200 Subject: [PATCH 03/13] Fix dependencies --- .mvn/maven.config | 1 - pom.xml | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.mvn/maven.config b/.mvn/maven.config index 66d406fe..2a0299c4 100644 --- a/.mvn/maven.config +++ b/.mvn/maven.config @@ -1,3 +1,2 @@ -Pconsume-incrementals -Pmight-produce-incrementals --Duse-jenkins-bom diff --git a/pom.xml b/pom.xml index e42ded9c..bee9e2ac 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ org.jenkins-ci.plugins plugin - 4.4 + 4.6 org.jenkins-ci.plugins.workflow @@ -84,7 +84,7 @@ org.jenkins-ci.plugins.workflow workflow-api - 2.33 + 2.40 org.jenkins-ci.plugins.workflow @@ -149,7 +149,7 @@ org.jenkins-ci.plugins structs - 1.18 + 1.20 org.jenkins-ci.plugins From 4877c2c2021e02fe80db0325551583dea2ad6b40 Mon Sep 17 00:00:00 2001 From: Devin Nusbaum Date: Wed, 12 Aug 2020 17:13:07 -0400 Subject: [PATCH 04/13] [JENKINS-62014] Add smoke test for env var filters --- pom.xml | 6 ++++++ .../steps/durable_task/ShellStepTest.java | 20 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/pom.xml b/pom.xml index bee9e2ac..fa99c7bd 100644 --- a/pom.xml +++ b/pom.xml @@ -156,5 +156,11 @@ scm-api 2.2.6 + + io.jenkins.plugins + generic-environment-filters + 1.1 + test + diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java index c0e54af5..ba855184 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java @@ -32,6 +32,8 @@ import hudson.slaves.EnvironmentVariablesNodeProperty; import hudson.tasks.BatchFile; import hudson.tasks.Shell; +import io.jenkins.plugins.generic_environment_filters.RemoveSpecificVariablesFilter; +import io.jenkins.plugins.generic_environment_filters.VariableContributingFilter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; @@ -54,6 +56,7 @@ import java.util.logging.Level; import java.util.logging.LogRecord; import javax.annotation.CheckForNull; +import jenkins.tasks.filters.EnvVarsFilterGlobalConfiguration; import jenkins.util.JenkinsJVM; import org.apache.commons.lang.StringUtils; @@ -724,6 +727,23 @@ private static final class HelloNote extends ConsoleNote> { j.waitForMessage("Timeout has been exceeded", b); // TODO assertLogContains fails unless a sleep is introduced; possible race condition in waitForCompletion } + @Issue("JENKINS-62014") + @Test public void envVarFilters() throws Exception { + EnvVarsFilterGlobalConfiguration.getAllActivatedGlobalRules().add(new RemoveSpecificVariablesFilter("FOO", "TODO: UNUSED")); + EnvVarsFilterGlobalConfiguration.getAllActivatedGlobalRules().add(new VariableContributingFilter("BAZ", "QUX")); + WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); + p.setDefinition(new CpsFlowDefinition( + "node() {\n" + + " withEnv(['FOO=BAR']) {\n" + + " sh('echo FOO=$FOO and BAZ=$BAZ')\n" + + " }\n" + + "}", true)); + WorkflowRun b = j.buildAndAssertSuccess(p); + j.assertLogContains("FOO=", b); + j.assertLogNotContains("FOO=BAR", b); + j.assertLogContains("BAZ=QUX", b); + } + /** * Asserts that the predicate remains true up to the given timeout. */ From bea22a5a462d145ce69845a8c40788df83b4ba9f Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Thu, 13 Aug 2020 10:21:22 +0200 Subject: [PATCH 05/13] Update to generic-environment-filters 1.2 for the test --- pom.xml | 2 +- .../plugins/workflow/steps/durable_task/ShellStepTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index fa99c7bd..e08758d3 100644 --- a/pom.xml +++ b/pom.xml @@ -159,7 +159,7 @@ io.jenkins.plugins generic-environment-filters - 1.1 + 1.2 test diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java index ba855184..5bc6395e 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java @@ -729,7 +729,7 @@ private static final class HelloNote extends ConsoleNote> { @Issue("JENKINS-62014") @Test public void envVarFilters() throws Exception { - EnvVarsFilterGlobalConfiguration.getAllActivatedGlobalRules().add(new RemoveSpecificVariablesFilter("FOO", "TODO: UNUSED")); + EnvVarsFilterGlobalConfiguration.getAllActivatedGlobalRules().add(new RemoveSpecificVariablesFilter("FOO")); EnvVarsFilterGlobalConfiguration.getAllActivatedGlobalRules().add(new VariableContributingFilter("BAZ", "QUX")); WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( From 8549da1db30dc2addf3ef3c061a3817a9de59620 Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Thu, 13 Aug 2020 10:36:56 +0200 Subject: [PATCH 06/13] Ensure the correct types are being listed --- .../workflow/steps/durable_task/ShellStepTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java index 5bc6395e..2d4fa3e1 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java @@ -19,6 +19,7 @@ import hudson.model.BooleanParameterDefinition; import hudson.model.BooleanParameterValue; import hudson.model.BuildListener; +import hudson.model.Descriptor; import hudson.model.FreeStyleProject; import hudson.model.Node; import hudson.model.ParametersAction; @@ -32,6 +33,7 @@ import hudson.slaves.EnvironmentVariablesNodeProperty; import hudson.tasks.BatchFile; import hudson.tasks.Shell; +import io.jenkins.plugins.environment_filter_utils.util.BuilderUtil; import io.jenkins.plugins.generic_environment_filters.RemoveSpecificVariablesFilter; import io.jenkins.plugins.generic_environment_filters.VariableContributingFilter; import java.io.ByteArrayOutputStream; @@ -61,6 +63,8 @@ import org.apache.commons.lang.StringUtils; import static org.hamcrest.Matchers.*; + +import org.hamcrest.MatcherAssert; import org.jenkinsci.plugins.durabletask.FileMonitoringTask; import org.jenkinsci.plugins.workflow.actions.ArgumentsAction; @@ -744,6 +748,15 @@ private static final class HelloNote extends ConsoleNote> { j.assertLogContains("BAZ=QUX", b); } + @Issue("JENKINS-62014") + @Test public void ensureTypes() throws Exception { + final List descriptors = BuilderUtil.allDescriptors(); + + MatcherAssert.assertThat(descriptors , containsInAnyOrder( + j.jenkins.getDescriptor(Shell.class), j.jenkins.getDescriptor(BatchFile.class), + j.jenkins.getDescriptor(BatchScriptStep.class), j.jenkins.getDescriptor(PowershellScriptStep.class), j.jenkins.getDescriptor(ShellStep.class), j.jenkins.getDescriptor(PowerShellCoreScriptStep.class))); + } + /** * Asserts that the predicate remains true up to the given timeout. */ From a557f2a867a7aa16a7a3ecb288dbf32a35c01eeb Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Thu, 13 Aug 2020 10:40:01 +0200 Subject: [PATCH 07/13] Update dependency versions to be compatible --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e08758d3..e0897bb3 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,7 @@ 2.248 8 true - 2.20 + 2.22 3.3 @@ -144,7 +144,7 @@ org.jenkins-ci.plugins script-security - 1.58 + 1.71 org.jenkins-ci.plugins From cc10978fe0291c8a5b0adf9f3ef68f4b5b05de28 Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Thu, 13 Aug 2020 11:36:57 +0200 Subject: [PATCH 08/13] Add JUnit to test dependencies, required by matrix-project --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index e0897bb3..3b3f79f8 100644 --- a/pom.xml +++ b/pom.xml @@ -162,5 +162,11 @@ 1.2 test + + org.jenkins-ci.plugins + junit + 1.29 + test + From cc3d063b264ef73a68bdac074ca785390e80ef2c Mon Sep 17 00:00:00 2001 From: Devin Nusbaum Date: Thu, 13 Aug 2020 10:37:47 -0400 Subject: [PATCH 09/13] Use plugin BOM to update dependencies --- pom.xml | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/pom.xml b/pom.xml index 3b3f79f8..2834b44a 100644 --- a/pom.xml +++ b/pom.xml @@ -67,46 +67,48 @@ 2.248 8 true - 2.22 - 3.3 + + + + io.jenkins.tools.bom + bom-2.235.x + 11 + import + pom + + + org.jenkins-ci.plugins.workflow workflow-step-api - ${workflow-step-api-plugin.version} org.jenkins-ci.plugins durable-task - 1.33 org.jenkins-ci.plugins.workflow workflow-api - 2.40 org.jenkins-ci.plugins.workflow workflow-support - ${workflow-support-plugin.version} org.jenkins-ci.plugins.workflow workflow-cps - 2.70 test org.jenkins-ci.plugins.workflow workflow-job - 2.31 test org.jenkins-ci.plugins.workflow workflow-basic-steps - 2.14 test @@ -118,43 +120,36 @@ org.jenkins-ci.plugins.workflow workflow-step-api - ${workflow-step-api-plugin.version} tests test org.jenkins-ci.plugins.workflow workflow-support - ${workflow-support-plugin.version} tests test org.jenkins-ci.plugins credentials-binding - 1.17 test org.jenkins-ci.plugins.workflow workflow-scm-step - 2.7 test org.jenkins-ci.plugins script-security - 1.71 org.jenkins-ci.plugins structs - 1.20 org.jenkins-ci.plugins scm-api - 2.2.6 io.jenkins.plugins @@ -162,11 +157,5 @@ 1.2 test - - org.jenkins-ci.plugins - junit - 1.29 - test - From 8bca029e129143cbd51457ecdfd4d5242bf2cd44 Mon Sep 17 00:00:00 2001 From: Devin Nusbaum Date: Thu, 13 Aug 2020 10:39:23 -0400 Subject: [PATCH 10/13] Don't run a CI build on Windows on Java 11 --- Jenkinsfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 70e42115..c5d64b97 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,6 +1,5 @@ buildPlugin(useAci: true, configurations: [ [platform: 'linux', jdk: '8'], [platform: 'windows', jdk: '8'], - [platform: 'linux', jdk: '11'], - [platform: 'windows', jdk: '11'] + [platform: 'linux', jdk: '11'] ]) From 69206da8bde143e630a659e58766f365fa2876f4 Mon Sep 17 00:00:00 2001 From: Devin Nusbaum Date: Thu, 13 Aug 2020 11:05:46 -0400 Subject: [PATCH 11/13] Fix ShellStepTest.envVarFilters on Windows --- .../plugins/workflow/steps/durable_task/ShellStepTest.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java index 2d4fa3e1..46506c80 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java @@ -739,7 +739,11 @@ private static final class HelloNote extends ConsoleNote> { p.setDefinition(new CpsFlowDefinition( "node() {\n" + " withEnv(['FOO=BAR']) {\n" + - " sh('echo FOO=$FOO and BAZ=$BAZ')\n" + + " if (isUnix()) {\n" + + " sh('echo FOO=$FOO and BAZ=$BAZ')\n" + + " } else {\n" + + " bat('ECHO FOO=%FOO% and BAZ=%BAZ%')\n" + + " }\n" + " }\n" + "}", true)); WorkflowRun b = j.buildAndAssertSuccess(p); From 031629477163f56e53bdc19949ddfe6f8ba1606e Mon Sep 17 00:00:00 2001 From: Devin Nusbaum Date: Fri, 14 Aug 2020 11:21:35 -0400 Subject: [PATCH 12/13] Fix ShellStepTest.abort on Windows Due to flakiness around killing processes on Windows (see JENKINS-59152), we wait until the build has completed before checking that the process on the agent has completed as well. --- .../plugins/workflow/steps/durable_task/ShellStepTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java index 46506c80..7f30fcfa 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java @@ -199,6 +199,10 @@ public void abort() throws Exception { b.getExecutor().interrupt(); + // It can take a while for the process to exit on Windows (see JENKINS-59152), so we wait for the build to + // complete and confirm that the process is no longer running after the build has already completed. + j.assertBuildStatus(Result.ABORTED, j.waitForCompletion(b)); + // touching should have stopped final long refTimestamp = Files.getLastModifiedTime(tmp).toMillis(); ensureForWhile(5000, tmp, tmpFile -> { @@ -208,8 +212,6 @@ public void abort() throws Exception { throw new UncheckedIOException(e); } }); - - j.assertBuildStatus(Result.ABORTED, j.waitForCompletion(b)); } @Issue("JENKINS-41339") From 0e2ed4c69ea30d98acf07763b13aa8a4d141700b Mon Sep 17 00:00:00 2001 From: Devin Nusbaum Date: Fri, 14 Aug 2020 12:10:56 -0400 Subject: [PATCH 13/13] Fix flaky disconnection-related tests in ExecutorStepTest Tests that kill agents after waiting for a file to be created were killing the agent before the sh step had finished launching. The tests now wait for log output from the sh step to be present before killing the agent. --- .../plugins/workflow/support/steps/ExecutorStepTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepTest.java index 06538bab..5dc01db9 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepTest.java @@ -339,13 +339,14 @@ private void startJnlpProc() throws Exception { new FileOutputStream(f1).close(); p.setDefinition(new CpsFlowDefinition( "node('dumbo') {\n" + - " sh 'touch \"" + f2 + "\"; while [ -f \"" + f1 + "\" ]; do sleep 1; done; echo finished waiting; rm \"" + f2 + "\"'\n" + + " sh 'touch \"" + f2 + "\"; while [ -f \"" + f1 + "\" ]; do echo waiting; sleep 1; done; echo finished waiting; rm \"" + f2 + "\"'\n" + " echo 'OK, done'\n" + "}", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); while (!f2.isFile()) { Thread.sleep(100); } + story.j.waitForMessage("waiting", b); assertTrue(b.isBuilding()); Computer c = s.toComputer(); assertNotNull(c); @@ -392,7 +393,7 @@ public void evaluate() throws Throwable { new FileOutputStream(f1).close(); p.setDefinition(new CpsFlowDefinition( "node('dumbo') {\n" + - " sh 'touch \"" + f2 + "\"; while [ -f \"" + f1 + "\" ]; do sleep 1; done; echo finished waiting; rm \"" + f2 + "\"'\n" + + " sh 'touch \"" + f2 + "\"; while [ -f \"" + f1 + "\" ]; do echo waiting; sleep 1; done; echo finished waiting; rm \"" + f2 + "\"'\n" + " sh 'echo Back again'\n" + " echo 'OK, done'\n" + "}", true)); @@ -401,6 +402,7 @@ public void evaluate() throws Throwable { while (!f2.isFile()) { Thread.sleep(100); } + story.j.waitForMessage("waiting", b); LOGGER.info("f2 created, first sh running"); assertTrue(b.isBuilding()); Computer computer = s.toComputer();