- import groovy.mock.interceptor.MockFor
- import static groovy.test.GroovyAssert.*
- import groovy.util.GroovyTestCase
-
- import org.wikimedia.integration.Pipeline
- import org.wikimedia.integration.PipelineRunner
- import org.wikimedia.integration.PipelineStage
- import org.wikimedia.integration.ExecutionGraph
- import org.wikimedia.integration.ExecutionContext
-
- class PipelineStageTest extends GroovyTestCase {
- private class WorkflowScript {} // Mock for Jenkins Pipeline workflow context
-
- void testDefaultConfig_shortHand() {
- // shorthand with just name is: build and run a variant
- def cfg = [name: "foo"]
-
- assert PipelineStage.defaultConfig(cfg) == [
- name: "foo",
- build: '${.stage}',
- run: [
- image: '${.imageID}',
- arguments: [],
- ],
- ]
- }
-
- void testDefaultConfig_run() {
- def cfg = [
- name: "foo",
- build: "foo",
- run: true,
- ]
-
- assert PipelineStage.defaultConfig(cfg) == [
- name: "foo",
- build: "foo",
-
- // run: true means run the built image
- run: [
- image: '${.imageID}',
- arguments: [],
- ],
- ]
- }
-
- void testDefaultConfig_publish() {
- def cfg = [
- publish: [
- image: true,
- ],
- ]
-
- assert PipelineStage.defaultConfig(cfg) == [
- publish: [
- image: [
- // defaults to the previously built image
- id: '${.imageID}',
-
- // defaults to the project name
- name: '${setup.project}',
-
- // defaults to the pipeline start timestamp and this stage name
- tag: '${setup.timestamp}-${.stage}',
-
- // defaults to []
- tags: [],
- ],
- ],
- ]
- }
-
- void testDefaultConfig_deploy() {
- def cfg = [
- deploy: [
- chart: "chart.tar.gz",
- ],
- ]
-
- assert PipelineStage.defaultConfig(cfg) == [
- deploy: [
- chart: "chart.tar.gz",
-
- // defaults to the previously published image
- image: '${.publishedImage}',
-
- // defaults to "ci"
- cluster: "ci",
-
- // defaults to true
- test: true,
- ],
- ]
-
- cfg = [
- deploy: [
- chart: "chart.tar.gz",
- image: "fooimage",
- cluster: "foocluster",
- test: true,
- ],
- ]
-
- assert PipelineStage.defaultConfig(cfg) == [
- deploy: [
- chart: "chart.tar.gz",
- image: "fooimage",
- cluster: "foocluster",
- test: true,
- ],
- ]
- }
-
- void testBuild() {
- def pipeline = new Pipeline("foo", [
- stages: [
- [
- name: "foo",
- build: "foovariant",
- ],
- ]
- ])
-
- def mockRunner = new MockFor(PipelineRunner)
- def stack = pipeline.stack()
- def stage = stack[1][0]
-
- stubStageContexts(stack, [
- setup: { ctx ->
- ctx["imageLabels"] = [foo: "foolabel", bar: "barlabel"]
- },
- ])
-
- mockRunner.demand.build { variant, labels ->
- assert variant == "foovariant"
- assert labels == [foo: "foolabel", bar: "barlabel"]
-
- "foo-image-id"
- }
-
- mockRunner.use {
- def ws = new WorkflowScript()
- def runner = new PipelineRunner(ws)
-
- stage.build(ws, runner)
- }
-
- assert stage.context["imageID"] == "foo-image-id"
- }
-
- void testDeploy_withTest() {
- def pipeline = new Pipeline("foo", [
- stages: [
- [
- name: "foo",
- build: "foovariant",
- publish: [
- image: true,
- ],
- ],
- [
- name: "bar",
- deploy: [
- image: '${foo.publishedImage}',
- chart: 'https://an.example/chart/foo-${.stage}.tar.gz',
- tag: '${.stage}-tag',
- test: true,
- ],
- ],
- ]
- ])
-
- def mockRunner = new MockFor(PipelineRunner)
- def stack = pipeline.stack()
- def stage = stack[2][0]
-
- stubStageContexts(stack, [
- foo: { ctx ->
- ctx["imageID"] = "foo-image-id"
-
- ctx["imageName"] = "foo-project"
- ctx["imageFullName"] = "registry.example/bar/foo-project"
- ctx["imageTag"] = "0000-00-00-000000-foo"
- ctx["imageTags"] = ["0000-00-00-000000-foo"]
- ctx["publishedImage"] = "registry.example/bar/foo-project:0000-00-00-000000-foo"
- },
- ])
-
- mockRunner.demand.deployWithChart { chart, image, tag ->
- assert chart == "https://an.example/chart/foo-bar.tar.gz"
- assert image == "registry.example/bar/foo-project:0000-00-00-000000-foo"
- assert tag == "bar-tag"
-
- "bar-release-name"
- }
-
- mockRunner.demand.testRelease { releaseName ->
- assert releaseName == "bar-release-name"
- }
-
- mockRunner.use {
- def ws = new WorkflowScript()
- def runner = new PipelineRunner(ws)
-
- stage.deploy(ws, runner)
- }
-
- assert stage.context["releaseName"] == "bar-release-name"
- }
-
- void testDeploy_withoutTest() {
- def pipeline = new Pipeline("foo", [
- stages: [
- [
- name: "foo",
- build: "foovariant",
- publish: [
- image: true,
- ],
- ],
- [
- name: "bar",
- deploy: [
- image: '${foo.publishedImage}',
- chart: 'https://an.example/chart/foo-${.stage}.tar.gz',
- tag: '${.stage}-tag',
- test: false,
- ],
- ],
- ]
- ])
-
- def mockRunner = new MockFor(PipelineRunner)
- def stack = pipeline.stack()
- def stage = stack[2][0]
-
- stubStageContexts(stack, [
- foo: { ctx ->
- ctx["imageID"] = "foo-image-id"
-
- ctx["imageName"] = "foo-project"
- ctx["imageFullName"] = "registry.example/bar/foo-project"
- ctx["imageTag"] = "0000-00-00-000000-foo"
- ctx["imageTags"] = ["0000-00-00-000000-foo"]
- ctx["publishedImage"] = "registry.example/bar/foo-project:0000-00-00-000000-foo"
- },
- ])
-
- mockRunner.demand.deployWithChart { chart, image, tag ->
- assert chart == "https://an.example/chart/foo-bar.tar.gz"
- assert image == "registry.example/bar/foo-project:0000-00-00-000000-foo"
- assert tag == "bar-tag"
-
- "bar-release-name"
- }
-
- mockRunner.use {
- def ws = new WorkflowScript()
- def runner = new PipelineRunner(ws)
-
- stage.deploy(ws, runner)
- }
-
- assert stage.context["releaseName"] == "bar-release-name"
- }
-
- void testExports() {
- def pipeline = new Pipeline("foo", [
- stages: [
- [
- name: "foo",
- build: "foovariant",
- exports: [
- thing: '${.imageID}-${setup.timestamp}',
- ],
- ],
- ]
- ])
-
- def mockRunner = new MockFor(PipelineRunner)
- def mockWS = new MockFor(WorkflowScript)
- def stack = pipeline.stack()
- def stage = stack[1][0]
-
- stubStageContexts(stack, [
- setup: { ctx ->
- ctx["timestamp"] = "0000-00-00-000000"
- },
- foo: { ctx ->
- ctx["imageID"] = "foo-image-id"
- },
- ])
-
- mockWS.demand.echo { msg ->
- assert msg == "exported foo.thing='foo-image-id-0000-00-00-000000'"
- }
-
- mockWS.use {
- mockRunner.use {
- def ws = new WorkflowScript()
- def runner = new PipelineRunner(ws)
-
- stage.exports(ws, runner)
- }
- }
-
- assert stage.context["thing"] == "foo-image-id-0000-00-00-000000"
- }
-
- void testPublish() {
- def pipeline = new Pipeline("foopipeline", [
- stages: [
- [
- name: "built",
- build: "foovariant",
- ],
- [
- name: "published",
- publish: [
- image: [
- id: '${built.imageID}',
- ],
- ],
- ]
- ]
- ])
-
- def mockRunner = new MockFor(PipelineRunner)
- def stack = pipeline.stack()
- def stage = stack[2][0]
-
- stubStageContexts(stack, [
- setup: { ctx ->
- ctx["project"] = "foo-project"
- ctx["timestamp"] = "0000-00-00-000000"
- ctx["imageLabels"] = []
- },
- built: { ctx ->
- ctx["imageID"] = "foo-image-id"
- },
- ])
-
- mockRunner.demand.registerAs { imageID, imageName, tag ->
- assert imageID == "foo-image-id"
- assert imageName == "foo-project"
- assert tag == "0000-00-00-000000-published"
- }
-
- mockRunner.demand.qualifyRegistryPath { imageName ->
- assert imageName == "foo-project"
-
- "registry.example/bar/foo-project"
- }
-
- mockRunner.use {
- def ws = new WorkflowScript()
- def runner = new PipelineRunner(ws)
-
- stage.publish(ws, runner)
- }
-
- assert stage.context["imageName"] == "foo-project"
- assert stage.context["imageFullName"] == "registry.example/bar/foo-project"
- assert stage.context["imageTag"] == "0000-00-00-000000-published"
- assert stage.context["imageTags"] == ["0000-00-00-000000-published"]
- assert stage.context["publishedImage"] == "registry.example/bar/foo-project:0000-00-00-000000-published"
- }
-
- void testRun() {
- def pipeline = new Pipeline("foo", [
- stages: [
- [
- name: "foo",
- build: "foovariant",
- ],
- [
- name: "bar",
- run: [
- image: '${foo.imageID}',
- arguments: ['${.stage}arg'],
- ],
- ],
- ]
- ])
-
- def mockRunner = new MockFor(PipelineRunner)
- def stack = pipeline.stack()
- def stage = stack[2][0]
-
- stubStageContexts(stack, [
- foo: { ctx ->
- ctx["imageID"] = "foo-image-id"
- },
- ])
-
- mockRunner.demand.run { image, args ->
- assert image == "foo-image-id"
- assert args == ["bararg"]
- }
-
- mockRunner.use {
- def ws = new WorkflowScript()
- def runner = new PipelineRunner(ws)
-
- stage.run(ws, runner)
- }
- }
-
- private void stubStageContexts(stack, stubs) {
- stack.each { stages ->
- stages.each { stage ->
- stage.context["stage"] = stage.name
-
- stubs.each { stageName, stub ->
- if (stage.name == stageName) {
- stub(stage.context)
- }
- }
- }
- }
- }
- }
|