Skip to content

Commit

Permalink
feat(stages): Update canManuallySkip to look at stage context and ove…
Browse files Browse the repository at this point in the history
…rride it on the PipelineStage to enable pipeline stages to be skippable. (#3927)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
haleyw and mergify[bot] committed Sep 25, 2020
1 parent 49b2ed1 commit 038885f
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 24 deletions.
Expand Up @@ -120,7 +120,7 @@ static String getType(Class<? extends StageDefinitionBuilder> clazz) {
}

/** Return true if the stage can be manually skipped from the API. */
default boolean canManuallySkip() {
default boolean canManuallySkip(StageExecution stage) {
return false;
}

Expand Down
Expand Up @@ -120,4 +120,9 @@ public CancellableStage.Result cancel(StageExecution stage) {

return new CancellableStage.Result(stage, emptyMap());
}

@Override
public boolean canManuallySkip(StageExecution stage) {
return (Boolean) stage.getContext().getOrDefault("skippable", false);
}
}
Expand Up @@ -22,35 +22,54 @@ import com.netflix.spinnaker.orca.pipeline.persistence.ExecutionRepository
import spock.lang.Specification
import spock.lang.Subject
import spock.lang.Unroll

import static com.netflix.spinnaker.orca.api.pipeline.models.ExecutionType.PIPELINE

class PipelineStageSpec extends Specification {
def executionRepository = Mock(ExecutionRepository)
def executionRepository = Mock(ExecutionRepository)

@Subject
def pipelineStage = new PipelineStage(executionRepository)

@Unroll
def "should cancel child pipeline (if started and not already canceled)"() {
given:
def childPipeline = PipelineExecutionImpl.newPipeline("childPipeline")
childPipeline.canceled = childPipelineIsCanceled
def stage = new StageExecutionImpl(PipelineExecutionImpl.newPipeline("orca"), "pipeline", stageContext)
and:
executionRepository.retrieve(PIPELINE, stageContext.executionId) >> childPipeline
@Subject
def pipelineStage = new PipelineStage(executionRepository)
when:
pipelineStage.cancel(stage)
@Unroll
def "should cancel child pipeline (if started and not already canceled)"() {
given:
def childPipeline = PipelineExecutionImpl.newPipeline("childPipeline")
childPipeline.canceled = childPipelineIsCanceled
then:
(shouldCancel ? 1 : 0) * executionRepository.cancel(PIPELINE, stageContext.executionId, "parent pipeline", null)
def stage = new StageExecutionImpl(PipelineExecutionImpl.newPipeline("orca"), "pipeline", stageContext)
where:
stageContext || childPipelineIsCanceled || shouldCancel
[:] || false || false // child pipeline has not started
[executionId: "sub-pipeline-id"] || false || true // child pipeline has started and should cancel
[executionId: "sub-pipeline-id"] || true || false // child pipeline has already been canceled
}
and:
executionRepository.retrieve(PIPELINE, stageContext.executionId) >> childPipeline
@Unroll
def "should skip pipeline if manually skipped"() {
given:
def stage = new StageExecutionImpl(PipelineExecutionImpl.newPipeline("testapp"), "pipeline", stageContext)
when:
pipelineStage.cancel(stage)
when:
def canSkip = pipelineStage.canManuallySkip(stage)
then:
(shouldCancel ? 1 : 0) * executionRepository.cancel(PIPELINE, stageContext.executionId, "parent pipeline", null)
then:
assert canSkip == expectCanSkip
where:
stageContext || childPipelineIsCanceled || shouldCancel
[:] || false || false // child pipeline has not started
[executionId: "sub-pipeline-id"] || false || true // child pipeline has started and should cancel
[executionId: "sub-pipeline-id"] || true || false // child pipeline has already been canceled
}
where:
stageContext || expectCanSkip
[:] || false
[skippable: true] || true
[skippable: false] || false
}
}
Expand Up @@ -39,7 +39,7 @@ fun StageDefinitionBuilder.buildTasks(stage: StageExecution) {
}

fun StageDefinitionBuilder.addContextFlags(stage: StageExecution) {
if (canManuallySkip()) {
if (canManuallySkip(stage)) {
// Provides a flag for the UI to indicate that the stage can be skipped.
stage.context["canManuallySkip"] = true
}
Expand Down
Expand Up @@ -493,7 +493,7 @@ class TaskController {
// If other execution mutations need validation, factor this out.
void validateStageUpdate(StageExecution stage) {
if (stage.context.manualSkip
&& !stageDefinitionBuilderFactory.builderFor(stage)?.canManuallySkip()) {
&& !stageDefinitionBuilderFactory.builderFor(stage)?.canManuallySkip(stage)) {
throw new CannotUpdateExecutionStage("Cannot manually skip stage.")
}
}
Expand Down

0 comments on commit 038885f

Please sign in to comment.