/** * A Stage is optional if it has an {@link OptionalStageEvaluator} in its * context that evaluates {@code false}. */ public static boolean isOptional(Stage stage, ContextParameterProcessor contextParameterProcessor) { Map stageEnabled = (Map) stage.getContext().get("stageEnabled"); String type = stageEnabled == null ? null : (String) stageEnabled.get("type"); String optionalType = type == null ? null : type.toLowerCase(); if (!OPTIONAL_STAGE_TYPES.containsKey(optionalType)) { if (stage.getSyntheticStageOwner() != null || stage.getParentStageId() != null) { Stage parentStage = stage .getExecution() .getStages() .stream() .filter(it -> it.getId().equals(stage.getParentStageId())) .findFirst() .orElseThrow(() -> new IllegalStateException(format("stage %s not found", stage.getParentStageId()))); return isOptional(parentStage, contextParameterProcessor); } return false; } try { return !stage.mapTo("/stageEnabled", OPTIONAL_STAGE_TYPES.get(optionalType)).evaluate(stage, contextParameterProcessor); } catch (InvalidExpression e) { log.warn("Unable to determine stage optionality, reason: {} (executionId: {}, stageId: {})", e.getMessage(), stage.getExecution().getId(), stage.getId()); return false; } }