use of hudson.model.TaskListener in project sonar-scanner-jenkins by SonarSource.
the class BuilderUtilsTest method buildEnv.
@Test
public void buildEnv() throws IOException, InterruptedException {
TaskListener l = mock(TaskListener.class);
AbstractBuild<?, ?> r = mock(AbstractBuild.class);
EnvVars env = new EnvVars("key", "value", "key2", "value2");
when(r.getEnvironment(l)).thenReturn(env);
when(r.getBuildVariables()).thenReturn(ImmutableMap.of("key", "newValue"));
env = BuilderUtils.getEnvAndBuildVars(r, l);
assertThat(env.descendingMap()).contains(entry("key", "newValue"), entry("key2", "value2"));
}
use of hudson.model.TaskListener in project workflow-cps-plugin by jenkinsci.
the class DSL method reportAmbiguousStepInvocation.
private void reportAmbiguousStepInvocation(CpsStepContext context, StepDescriptor d, @Nullable TaskListener listener) {
if (listener != null) {
List<String> ambiguousClassNames = StepDescriptor.all().stream().filter(sd -> sd.getFunctionName().equals(d.getFunctionName())).map(sd -> sd.clazz.getName()).collect(Collectors.toList());
String message = String.format("Warning: Invoking ambiguous Pipeline Step ā%1$sā (%2$s). " + "ā%1$sā could refer to any of the following steps: %3$s. " + "You can invoke steps by class name instead to avoid ambiguity. " + "For example: steps.'%2$s'(...)", d.getFunctionName(), d.clazz.getName(), ambiguousClassNames);
listener.getLogger().println(message);
return;
}
LOGGER.log(Level.FINE, "Unable to report ambiguous step invocation for: " + d.getFunctionName());
}
use of hudson.model.TaskListener in project workflow-cps-plugin by jenkinsci.
the class DSL method invokeStep.
/**
* When {@link #invokeMethod(String, Object)} is calling a {@link StepDescriptor}
* @param d The {@link StepDescriptor} being invoked.
* @param name The name used to invoke the step. May be {@link StepDescriptor#getFunctionName}, a symbol as in {@link StepDescriptor#metaStepsOf}, or {@code d.clazz.getName()}.
* @param args The arguments passed to the step.
*/
protected Object invokeStep(StepDescriptor d, String name, Object args) {
final NamedArgsAndClosure ps = parseArgs(args, d);
CpsThread thread = CpsThread.current();
FlowNode an;
// TODO: generalize the notion of Step taking over the FlowNode creation.
boolean hack = d instanceof ParallelStep.DescriptorImpl || d instanceof LoadStep.DescriptorImpl;
if (ps.body == null && !hack) {
if (!(d.getClass().getName().equals("org.jenkinsci.plugins.workflow.support.steps.StageStep$DescriptorImpl")) && d.takesImplicitBlockArgument()) {
throw new IllegalStateException(String.format("%s step must be called with a body", name));
} else {
an = new StepAtomNode(exec, d, thread.head.get());
}
} else {
an = new StepStartNode(exec, d, thread.head.get());
}
final CpsStepContext context = new CpsStepContext(d, thread, handle, an, ps.body);
EnvVars allEnv = null;
Set<String> sensitiveVariables = Collections.emptySet();
try {
allEnv = context.get(EnvVars.class);
EnvironmentExpander envExpander = context.get(EnvironmentExpander.class);
if (envExpander != null) {
sensitiveVariables = new HashSet<>(envExpander.getSensitiveVariables());
}
} catch (IOException | InterruptedException e) {
LOGGER.log(Level.WARNING, "Unable to retrieve environment variables", e);
}
// Ensure ArgumentsAction is attached before we notify even synchronous listeners:
ArgumentsActionImpl argumentsAction = null;
try {
// No point storing empty arguments, and ParallelStep is a special case where we can't store its closure arguments
if (ps.namedArgs != null && !(ps.namedArgs.isEmpty()) && isKeepStepArguments() && !(d instanceof ParallelStep.DescriptorImpl)) {
// Get the environment variables to find ones that might be credentials bindings
Computer comp = context.get(Computer.class);
if (comp != null && allEnv != null) {
allEnv.entrySet().removeAll(comp.getEnvironment().entrySet());
}
argumentsAction = new ArgumentsActionImpl(ps.namedArgs, allEnv, sensitiveVariables);
an.addAction(argumentsAction);
}
} catch (Exception e) {
// Avoid breaking execution because we can't store some sort of crazy Step argument
LOGGER.log(Level.WARNING, "Error storing the arguments for step: " + d.getFunctionName(), e);
}
// TODO: use CPS call stack to obtain the current call site source location. See JENKINS-23013
thread.head.setNewHead(an);
Step s;
boolean sync;
ClassLoader originalLoader = Thread.currentThread().getContextClassLoader();
try {
TaskListener listener = context.get(TaskListener.class);
logInterpolationWarnings(name, argumentsAction, ps.interpolatedStrings, allEnv, sensitiveVariables, listener);
if (unreportedAmbiguousFunctions.remove(name)) {
reportAmbiguousStepInvocation(context, d, listener);
}
d.checkContextAvailability(context);
Thread.currentThread().setContextClassLoader(CpsVmExecutorService.ORIGINAL_CONTEXT_CLASS_LOADER.get());
if (Util.isOverridden(StepDescriptor.class, d.getClass(), "newInstance", Map.class)) {
s = d.newInstance(ps.namedArgs);
} else {
DescribableModel<? extends Step> stepModel = DescribableModel.of(d.clazz);
s = stepModel.instantiate(ps.namedArgs, listener);
}
// Persist the node - block start and end nodes do their own persistence.
CpsFlowExecution.maybeAutoPersistNode(an);
// Call any registered StepListeners.
for (StepListener sl : ExtensionList.lookup(StepListener.class)) {
try {
sl.notifyOfNewStep(s, context);
} catch (Throwable e) {
LOGGER.log(Level.WARNING, "failed to notify step listener before starting " + s.getDescriptor().getFunctionName(), e);
}
}
if (!context.isCompleted()) {
StepExecution e = s.start(context);
thread.setStep(e);
sync = e.start();
} else {
s = null;
sync = true;
}
} catch (Exception e) {
context.onFailure(e);
s = null;
sync = true;
} finally {
Thread.currentThread().setContextClassLoader(originalLoader);
}
if (sync) {
assert context.withBodyInvokers(List::isEmpty) : "If a step claims synchronous completion, it shouldn't invoke body";
if (context.getOutcome() == null) {
context.onFailure(new AssertionError("Step " + s + " claimed to have ended synchronously, but didn't set the result via StepContext.onSuccess/onFailure"));
}
thread.setStep(null);
// we just move on accordingly
if (an instanceof StepStartNode) {
// no body invoked, so EndNode follows StartNode immediately.
thread.head.setNewHead(new StepEndNode(exec, (StepStartNode) an, an));
}
thread.head.markIfFail(context.getOutcome());
return context.replay();
} else {
// if it's in progress, suspend it until we get invoked later.
// when it resumes, the CPS caller behaves as if this method returned with the resume value
Continuable.suspend(name, new ThreadTaskImpl(context));
// so the execution will never reach here.
throw new AssertionError();
}
}
use of hudson.model.TaskListener in project workflow-cps-plugin by jenkinsci.
the class DSL method logInterpolationWarnings.
private void logInterpolationWarnings(String stepName, @CheckForNull ArgumentsActionImpl argumentsAction, Set<String> interpolatedStrings, @CheckForNull EnvVars envVars, @NonNull Set<String> sensitiveVariables, TaskListener listener) throws IOException {
if (UNSAFE_GROOVY_INTERPOLATION.equals("ignore")) {
return;
}
boolean shouldFail;
if (UNSAFE_GROOVY_INTERPOLATION.equals("fail")) {
shouldFail = true;
} else {
shouldFail = false;
}
if (argumentsAction == null || interpolatedStrings.isEmpty() || envVars == null || envVars.isEmpty() || sensitiveVariables.isEmpty()) {
return;
}
// Workaround for NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE false positive in lambdas: https://github.com/spotbugs/spotbugs/issues/552.
final EnvVars nonNullEnvVars = envVars;
List<String> scanResults = sensitiveVariables.stream().filter(e -> !nonNullEnvVars.get(e, "").isEmpty() && interpolatedStrings.stream().anyMatch(g -> g.contains(nonNullEnvVars.get(e)))).collect(Collectors.toList());
if (scanResults != null && !scanResults.isEmpty()) {
String warningType;
if (shouldFail) {
warningType = "Error";
} else {
warningType = "Warning";
}
String warning = String.format("%s: A secret was passed to \"%s\" using Groovy String interpolation, which is insecure.%n\t\t Affected argument(s) used the following variable(s): %s%n\t\t See https://jenkins.io/redirect/groovy-string-interpolation for details.", warningType, stepName, scanResults.toString());
FlowExecutionOwner owner = exec.getOwner();
if (owner != null && owner.getExecutable() instanceof Run) {
InterpolatedSecretsAction runReport = ((Run) owner.getExecutable()).getAction(InterpolatedSecretsAction.class);
if (runReport == null) {
runReport = new InterpolatedSecretsAction();
((Run) owner.getExecutable()).addAction(runReport);
}
runReport.record(stepName, scanResults);
} else {
LOGGER.log(Level.FINE, "Unable to generate Interpolated Secrets Report");
}
if (shouldFail) {
throw new AbortException(warning);
} else {
listener.getLogger().println(warning);
}
}
}
use of hudson.model.TaskListener in project workflow-cps-plugin by jenkinsci.
the class EnvActionImpl method getProperty.
@Override
public String getProperty(String propertyName) {
try {
CpsThread t = CpsThread.current();
TaskListener listener = getListener();
return EnvironmentExpander.getEffectiveEnvironment(getEnvironment(listener), t.getContextVariable(EnvVars.class, this::getExecution, this::getNode), t.getContextVariable(EnvironmentExpander.class, this::getExecution, this::getNode), null, listener).get(propertyName);
} catch (Exception x) {
LOGGER.log(Level.WARNING, null, x);
return null;
}
}
Aggregations