Skip to content

Instantly share code, notes, and snippets.

@ghale
Last active June 24, 2020 18:53
Show Gist options
  • Save ghale/f825372b1c738c5d9e60cfa03cde14f6 to your computer and use it in GitHub Desktop.
Save ghale/f825372b1c738c5d9e60cfa03cde14f6 to your computer and use it in GitHub Desktop.
Create arbitrary pipelines within a build
// Set up two different pipelines
createPipeline("foo")
createPipeline("bar")
// Insert a cleanup task that is automatically slotted into the foo "prepare" phase
tasks.register("cleanupFoo", Cleanup) { pipelineName = "foo" }
// Insert a start task that is automatically slotted into the foo "start" phase
tasks.register("startFooTestContainer", StartContainer) { pipelineName = "foo" }
// Insert some more tasks that are slotted into the correct phase of the foo pipeline
tasks.register("runTestFoo1", ServerTest) { pipelineName = "foo" }
tasks.register("runTestFoo2", ServerTest) { pipelineName = "foo" }
tasks.register("runTestFoo3", ServerTest) { pipelineName = "foo" }
tasks.register("stopFooTestContainer", StopContainer) { pipelineName = "foo" }
tasks.register("processFoo", ProcessResults) { pipelineName = "foo" }
// Insert a test task that is automatically slotted into the bar "test" phase
tasks.register("runTestBar", ServerTest) { pipelineName = "bar" }
// Insert an arbitrary task into the bar process phase (i.e. this task is not
// handled by any of the pre-defined rules)
def processBar = tasks.register("processBar") {
dependsOn phase(Phase.PERFORM_TESTS, "bar")
mustRunAfter phase(Phase.STOP_RESOURCES, "bar")
}
phase(Phase.PROCESS_RESULTS ,"bar").configureEach {
dependsOn processBar
}
// Convenience method to get the lifecycle task for a particular phase
def phase(Phase phase, String pipeline) {
tasks.withType(PhaseTask).matching { it.phase == phase && it.pipelineName == pipeline }
}
// Convenience method to get pipeline tasks
def pipelineTasks(Class<?> type, String pipeline) {
tasks.withType(type).matching { it.pipelineName == pipeline }
}
// This creates the pipeline by defining lifecycle tasks for each phase of the pipeline and declaring
// rules that say certain task types that are associated with this pipeline always get slotted into the
// appropriate pipeline phase
def createPipeline(String pipeline) {
// Set up the basic pipeline
def suffix = pipeline.capitalize()
def prepareTests = tasks.register("prepareTests${suffix}", PhaseTask) {
phase = Phase.PREPARE
pipelineName = pipeline
}
def startTestResources = tasks.register("startTestResources${suffix}", PhaseTask) {
phase = Phase.START_RESOURCES
pipelineName = pipeline
dependsOn prepareTests
}
def stopTestResources = tasks.register("stopTestResources${suffix}", PhaseTask) {
phase = Phase.STOP_RESOURCES
pipelineName = pipeline
}
def performTests = tasks.register("performTests${suffix}", PhaseTask) {
phase = Phase.PERFORM_TESTS
pipelineName = pipeline
dependsOn startTestResources
finalizedBy stopTestResources
}
def processTestResults = tasks.register("processTestResults${suffix}", PhaseTask) {
phase = Phase.PROCESS_RESULTS
pipelineName = pipeline
dependsOn performTests
mustRunAfter stopTestResources // May not be necessaary
}
// Define the task collections
def cleanupTasks = pipelineTasks(Cleanup, pipeline)
def startContainerTasks = pipelineTasks(StartContainer, pipeline)
def serverTestTasks = pipelineTasks(ServerTest, pipeline)
def stopContainerTasks = pipelineTasks(StopContainer, pipeline)
def processResultsTasks = pipelineTasks(ProcessResults, pipeline)
// set up some rules to automatically slot tasks into phases
// We do this in an afterEvaluate because we want these rules configured
// after the creation action of the tasks (where the pipeline is set)
afterEvaluate {
prepareTests.configure { dependsOn cleanupTasks }
startContainerTasks.configureEach { dependsOn prepareTests }
startTestResources.configure { dependsOn startContainerTasks }
serverTestTasks.configureEach {
dependsOn startTestResources
finalizedBy stopTestResources
finalizedBy stopContainerTasks
}
performTests.configure { dependsOn serverTestTasks }
stopTestResources.configure { dependsOn stopContainerTasks }
processResultsTasks.configureEach {
dependsOn performTests
mustRunAfter stopTestResources
}
processTestResults.configure { dependsOn processResultsTasks }
}
}
enum Phase {
PREPARE, START_RESOURCES, PERFORM_TESTS, STOP_RESOURCES, PROCESS_RESULTS
}
abstract class PipelineTask extends DefaultTask {
@Internal
String pipelineName
}
class PhaseTask extends PipelineTask {
@Internal
Phase phase
}
class Cleanup extends PipelineTask { }
class StartContainer extends PipelineTask { }
class ServerTest extends PipelineTask { }
class StopContainer extends PipelineTask { }
class ProcessResults extends PipelineTask { }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment