BigW Consortium Gitlab

gitlab_ci_yaml_processor_spec.rb 35.6 KB
Newer Older
1 2
require 'spec_helper'

Valery Sizov committed
3
module Ci
Douwe Maan committed
4
  describe GitlabCiYamlProcessor, lib: true do
5
    let(:path) { 'path' }
6

Valery Sizov committed
7 8 9 10 11 12 13 14 15
    describe "#builds_for_ref" do
      let(:type) { 'test' }

      it "returns builds if no branch specified" do
        config = YAML.dump({
          before_script: ["pwd"],
          rspec: { script: "rspec" }
        })

16
        config_processor = GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
17 18 19 20

        expect(config_processor.builds_for_stage_and_ref(type, "master").size).to eq(1)
        expect(config_processor.builds_for_stage_and_ref(type, "master").first).to eq({
          stage: "test",
21
          stage_idx: 1,
Valery Sizov committed
22 23 24
          except: nil,
          name: :rspec,
          only: nil,
25 26
          commands: "pwd\nrspec",
          tag_list: [],
Valery Sizov committed
27
          options: {},
Kamil Trzcinski committed
28 29
          allow_failure: false,
          when: "on_success"
Valery Sizov committed
30 31
        })
      end
32

33 34 35 36 37 38
      describe :only do
        it "does not return builds if only has another branch" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", only: ["deploy"] }
                             })
Valery Sizov committed
39

40
          config_processor = GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
41

42 43
          expect(config_processor.builds_for_stage_and_ref(type, "master").size).to eq(0)
        end
Valery Sizov committed
44

45 46 47 48 49
        it "does not return builds if only has regexp with another branch" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", only: ["/^deploy$/"] }
                             })
Valery Sizov committed
50

51
          config_processor = GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
52

53 54
          expect(config_processor.builds_for_stage_and_ref(type, "master").size).to eq(0)
        end
Valery Sizov committed
55

56 57 58 59 60
        it "returns builds if only has specified this branch" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", only: ["master"] }
                             })
Valery Sizov committed
61

62
          config_processor = GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
63

64 65
          expect(config_processor.builds_for_stage_and_ref(type, "master").size).to eq(1)
        end
Valery Sizov committed
66

67 68 69 70 71
        it "returns builds if only has a list of branches including specified" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", type: type, only: ["master", "deploy"] }
                             })
Valery Sizov committed
72

73
          config_processor = GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
74

75 76
          expect(config_processor.builds_for_stage_and_ref(type, "deploy").size).to eq(1)
        end
Valery Sizov committed
77

78 79 80 81 82
        it "returns builds if only has a branches keyword specified" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", type: type, only: ["branches"] }
                             })
Valery Sizov committed
83

84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
          config_processor = GitlabCiYamlProcessor.new(config, path)

          expect(config_processor.builds_for_stage_and_ref(type, "deploy").size).to eq(1)
        end

        it "does not return builds if only has a tags keyword" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", type: type, only: ["tags"] }
                             })

          config_processor = GitlabCiYamlProcessor.new(config, path)

          expect(config_processor.builds_for_stage_and_ref(type, "deploy").size).to eq(0)
        end

100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
        it "returns builds if only has a triggers keyword specified and a trigger is provided" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", type: type, only: ["triggers"] }
                             })

          config_processor = GitlabCiYamlProcessor.new(config, path)

          expect(config_processor.builds_for_stage_and_ref(type, "deploy", false, true).size).to eq(1)
        end

        it "does not return builds if only has a triggers keyword specified and no trigger is provided" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", type: type, only: ["triggers"] }
                             })

          config_processor = GitlabCiYamlProcessor.new(config, path)

          expect(config_processor.builds_for_stage_and_ref(type, "deploy").size).to eq(0)
        end

122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
        it "returns builds if only has current repository path" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", type: type, only: ["branches@path"] }
                             })

          config_processor = GitlabCiYamlProcessor.new(config, path)

          expect(config_processor.builds_for_stage_and_ref(type, "deploy").size).to eq(1)
        end

        it "does not return builds if only has different repository path" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", type: type, only: ["branches@fork"] }
                             })

          config_processor = GitlabCiYamlProcessor.new(config, path)

          expect(config_processor.builds_for_stage_and_ref(type, "deploy").size).to eq(0)
        end

        it "returns build only for specified type" do

          config = YAML.dump({
                               before_script: ["pwd"],
Kamil Trzcinski committed
148
                               rspec: { script: "rspec", type: "test", only: ["master", "deploy"] },
149 150 151
                               staging: { script: "deploy", type: "deploy", only: ["master", "deploy"] },
                               production: { script: "deploy", type: "deploy", only: ["master@path", "deploy"] },
                             })
Valery Sizov committed
152

Kamil Trzcinski committed
153
          config_processor = GitlabCiYamlProcessor.new(config, 'fork')
Valery Sizov committed
154

155
          expect(config_processor.builds_for_stage_and_ref("deploy", "deploy").size).to eq(2)
Kamil Trzcinski committed
156 157
          expect(config_processor.builds_for_stage_and_ref("test", "deploy").size).to eq(1)
          expect(config_processor.builds_for_stage_and_ref("deploy", "master").size).to eq(1)
158
        end
Valery Sizov committed
159 160
      end

161 162 163 164 165 166
      describe :except do
        it "returns builds if except has another branch" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", except: ["deploy"] }
                             })
Valery Sizov committed
167

168
          config_processor = GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
169

170 171 172 173 174 175 176 177 178 179 180 181 182
          expect(config_processor.builds_for_stage_and_ref(type, "master").size).to eq(1)
        end

        it "returns builds if except has regexp with another branch" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", except: ["/^deploy$/"] }
                             })

          config_processor = GitlabCiYamlProcessor.new(config, path)

          expect(config_processor.builds_for_stage_and_ref(type, "master").size).to eq(1)
        end
Valery Sizov committed
183

184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
        it "does not return builds if except has specified this branch" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", except: ["master"] }
                             })

          config_processor = GitlabCiYamlProcessor.new(config, path)

          expect(config_processor.builds_for_stage_and_ref(type, "master").size).to eq(0)
        end

        it "does not return builds if except has a list of branches including specified" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", type: type, except: ["master", "deploy"] }
                             })

          config_processor = GitlabCiYamlProcessor.new(config, path)

          expect(config_processor.builds_for_stage_and_ref(type, "deploy").size).to eq(0)
        end

        it "does not return builds if except has a branches keyword specified" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", type: type, except: ["branches"] }
                             })

          config_processor = GitlabCiYamlProcessor.new(config, path)

          expect(config_processor.builds_for_stage_and_ref(type, "deploy").size).to eq(0)
        end

        it "returns builds if except has a tags keyword" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", type: type, except: ["tags"] }
                             })

          config_processor = GitlabCiYamlProcessor.new(config, path)

          expect(config_processor.builds_for_stage_and_ref(type, "deploy").size).to eq(1)
        end

228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
        it "does not return builds if except has a triggers keyword specified and a trigger is provided" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", type: type, except: ["triggers"] }
                             })

          config_processor = GitlabCiYamlProcessor.new(config, path)

          expect(config_processor.builds_for_stage_and_ref(type, "deploy", false, true).size).to eq(0)
        end

        it "returns builds if except has a triggers keyword specified and no trigger is provided" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", type: type, except: ["triggers"] }
                             })

          config_processor = GitlabCiYamlProcessor.new(config, path)

          expect(config_processor.builds_for_stage_and_ref(type, "deploy").size).to eq(1)
        end

250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
        it "does not return builds if except has current repository path" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", type: type, except: ["branches@path"] }
                             })

          config_processor = GitlabCiYamlProcessor.new(config, path)

          expect(config_processor.builds_for_stage_and_ref(type, "deploy").size).to eq(0)
        end

        it "returns builds if except has different repository path" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", type: type, except: ["branches@fork"] }
                             })

          config_processor = GitlabCiYamlProcessor.new(config, path)

          expect(config_processor.builds_for_stage_and_ref(type, "deploy").size).to eq(1)
        end

        it "returns build except specified type" do
          config = YAML.dump({
                               before_script: ["pwd"],
Kamil Trzcinski committed
275 276 277
                               rspec: { script: "rspec", type: "test", except: ["master", "deploy", "test@fork"] },
                               staging: { script: "deploy", type: "deploy", except: ["master"] },
                               production: { script: "deploy", type: "deploy", except: ["master@fork"] },
278 279
                             })

Kamil Trzcinski committed
280
          config_processor = GitlabCiYamlProcessor.new(config, 'fork')
281

Kamil Trzcinski committed
282 283 284
          expect(config_processor.builds_for_stage_and_ref("deploy", "deploy").size).to eq(2)
          expect(config_processor.builds_for_stage_and_ref("test", "test").size).to eq(0)
          expect(config_processor.builds_for_stage_and_ref("deploy", "master").size).to eq(0)
285
        end
Valery Sizov committed
286
      end
287

288
    end
289 290 291 292 293 294 295
    
    describe "Scripts handling" do
      let(:config_data) { YAML.dump(config) }
      let(:config_processor) { GitlabCiYamlProcessor.new(config_data, path) }
      
      subject { config_processor.builds_for_stage_and_ref("test", "master").first }
      
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
      describe "before_script" do
        context "in global context" do
          let(:config) {
            {
              before_script: ["global script"],
              test: { script: ["script"] }
            }
          }
          
          it "return commands with scripts concencaced" do
            expect(subject[:commands]).to eq("global script\nscript")
          end
        end
 
        context "overwritten in local context" do
          let(:config) {
            {
              before_script: ["global script"],
              test: { before_script: ["local script"], script: ["script"] }
            }
          }

          it "return commands with scripts concencaced" do
            expect(subject[:commands]).to eq("local script\nscript")
          end
        end
      end

      describe "script" do
        let(:config) {
          {
            test: { script: ["script"] }
          }
        }

        it "return commands with scripts concencaced" do
          expect(subject[:commands]).to eq("script")
        end
      end

336 337 338 339 340 341 342 343 344 345 346 347 348
      describe "finally_script" do
        context "in global context" do
          let(:config) {
            {
              finally_script: ["finally_script"],
              test: { script: ["script"] }
            }
          }

          it "return finally_script in options" do
            expect(subject[:options][:finally_script]).to eq(["finally_script"])
          end
        end
349 350 351 352 353 354 355 356 357 358 359 360 361

        context "overwritten in local context" do
          let(:config) {
            {
              finally_script: ["local finally_script"],
              test: { finally_script: ["local finally_script"], script: ["script"] }
            }
          }

          it "return finally_script in options" do
            expect(subject[:options][:finally_script]).to eq(["local finally_script"])
          end
        end
362 363
      end
    end
364

Valery Sizov committed
365 366 367 368 369 370 371 372 373
    describe "Image and service handling" do
      it "returns image and service when defined" do
        config = YAML.dump({
                             image: "ruby:2.1",
                             services: ["mysql"],
                             before_script: ["pwd"],
                             rspec: { script: "rspec" }
                           })

374
        config_processor = GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
375 376 377 378 379

        expect(config_processor.builds_for_stage_and_ref("test", "master").size).to eq(1)
        expect(config_processor.builds_for_stage_and_ref("test", "master").first).to eq({
          except: nil,
          stage: "test",
380
          stage_idx: 1,
Valery Sizov committed
381 382
          name: :rspec,
          only: nil,
383 384
          commands: "pwd\nrspec",
          tag_list: [],
Valery Sizov committed
385 386 387 388
          options: {
            image: "ruby:2.1",
            services: ["mysql"]
          },
389 390
          allow_failure: false,
          when: "on_success"
Valery Sizov committed
391 392 393 394 395 396 397 398 399 400 401
        })
      end

      it "returns image and service when overridden for job" do
        config = YAML.dump({
                             image:         "ruby:2.1",
                             services:      ["mysql"],
                             before_script: ["pwd"],
                             rspec:         { image: "ruby:2.5", services: ["postgresql"], script: "rspec" }
                           })

402
        config_processor = GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
403 404 405 406 407

        expect(config_processor.builds_for_stage_and_ref("test", "master").size).to eq(1)
        expect(config_processor.builds_for_stage_and_ref("test", "master").first).to eq({
          except: nil,
          stage: "test",
408
          stage_idx: 1,
Valery Sizov committed
409 410
          name: :rspec,
          only: nil,
411 412
          commands: "pwd\nrspec",
          tag_list: [],
Valery Sizov committed
413 414 415 416
          options: {
            image: "ruby:2.5",
            services: ["postgresql"]
          },
417 418
          allow_failure: false,
          when: "on_success"
Valery Sizov committed
419 420
        })
      end
421 422
    end

Valery Sizov committed
423 424 425 426 427 428 429 430 431 432 433 434
    describe "Variables" do
      it "returns variables when defined" do
        variables = {
          var1: "value1",
          var2: "value2",
        }
        config = YAML.dump({
                             variables: variables,
                             before_script: ["pwd"],
                             rspec: { script: "rspec" }
                           })

435
        config_processor = GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
436 437
        expect(config_processor.variables).to eq(variables)
      end
438 439
    end

440 441 442 443 444 445 446
    describe "When" do
      %w(on_success on_failure always).each do |when_state|
        it "returns #{when_state} when defined" do
          config = YAML.dump({
                               rspec: { script: "rspec", when: when_state }
                             })

447
          config_processor = GitlabCiYamlProcessor.new(config, path)
448 449 450 451 452 453 454
          builds = config_processor.builds_for_stage_and_ref("test", "master")
          expect(builds.size).to eq(1)
          expect(builds.first[:when]).to eq(when_state)
        end
      end
    end

455 456 457
    describe "Caches" do
      it "returns cache when defined globally" do
        config = YAML.dump({
458
                             cache: { paths: ["logs/", "binaries/"], untracked: true, key: 'key' },
459 460 461 462 463 464 465 466 467 468 469
                             rspec: {
                               script: "rspec"
                             }
                           })

        config_processor = GitlabCiYamlProcessor.new(config)

        expect(config_processor.builds_for_stage_and_ref("test", "master").size).to eq(1)
        expect(config_processor.builds_for_stage_and_ref("test", "master").first[:options][:cache]).to eq(
          paths: ["logs/", "binaries/"],
          untracked: true,
470
          key: 'key',
471 472 473 474 475 476
        )
      end

      it "returns cache when defined in a job" do
        config = YAML.dump({
                             rspec: {
477
                               cache: { paths: ["logs/", "binaries/"], untracked: true, key: 'key' },
478 479 480 481 482 483 484 485 486 487
                               script: "rspec"
                             }
                           })

        config_processor = GitlabCiYamlProcessor.new(config)

        expect(config_processor.builds_for_stage_and_ref("test", "master").size).to eq(1)
        expect(config_processor.builds_for_stage_and_ref("test", "master").first[:options][:cache]).to eq(
          paths: ["logs/", "binaries/"],
          untracked: true,
488
          key: 'key',
489 490 491 492 493
        )
      end

      it "overwrite cache when defined for a job and globally" do
        config = YAML.dump({
494
                             cache: { paths: ["logs/", "binaries/"], untracked: true, key: 'global' },
495 496
                             rspec: {
                               script: "rspec",
497
                               cache: { paths: ["test/"], untracked: false, key: 'local' },
498 499 500 501 502 503 504 505 506
                             }
                           })

        config_processor = GitlabCiYamlProcessor.new(config)

        expect(config_processor.builds_for_stage_and_ref("test", "master").size).to eq(1)
        expect(config_processor.builds_for_stage_and_ref("test", "master").first[:options][:cache]).to eq(
          paths: ["test/"],
          untracked: false,
507
          key: 'local',
508 509 510 511
        )
      end
    end

512 513 514 515 516 517
    describe "Artifacts" do
      it "returns artifacts when defined" do
        config = YAML.dump({
                             image:         "ruby:2.1",
                             services:      ["mysql"],
                             before_script: ["pwd"],
518
                             rspec:         {
519
                               artifacts: { paths: ["logs/", "binaries/"], untracked: true, name: "custom_name" },
520 521
                               script: "rspec"
                             }
522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
                           })

        config_processor = GitlabCiYamlProcessor.new(config)

        expect(config_processor.builds_for_stage_and_ref("test", "master").size).to eq(1)
        expect(config_processor.builds_for_stage_and_ref("test", "master").first).to eq({
          except: nil,
          stage: "test",
          stage_idx: 1,
          name: :rspec,
          only: nil,
          commands: "pwd\nrspec",
          tag_list: [],
          options: {
            image: "ruby:2.1",
            services: ["mysql"],
538
            artifacts: {
539
              name: "custom_name",
540 541 542
              paths: ["logs/", "binaries/"],
              untracked: true
            }
543 544 545 546 547 548 549
          },
          when: "on_success",
          allow_failure: false
        })
      end
    end

550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
    describe "Dependencies" do
      let(:config) do
        {
          build1: { stage: 'build', script: 'test' },
          build2: { stage: 'build', script: 'test' },
          test1: { stage: 'test', script: 'test', dependencies: dependencies },
          test2: { stage: 'test', script: 'test' },
          deploy: { stage: 'test', script: 'test' }
        }
      end

      subject { GitlabCiYamlProcessor.new(YAML.dump(config)) }

      context 'no dependencies' do
        let(:dependencies) { }

        it { expect { subject }.to_not raise_error }
      end

      context 'dependencies to builds' do
570
        let(:dependencies) { ['build1', 'build2'] }
571 572 573 574

        it { expect { subject }.to_not raise_error }
      end

575 576 577 578 579 580
      context 'dependencies to builds defined as symbols' do
        let(:dependencies) { [:build1, :build2] }

        it { expect { subject }.to_not raise_error }
      end

581
      context 'undefined dependency' do
582
        let(:dependencies) { ['undefined'] }
583 584 585 586 587

        it { expect { subject }.to raise_error(GitlabCiYamlProcessor::ValidationError, 'test1 job: undefined dependency: undefined') }
      end

      context 'dependencies to deploy' do
588
        let(:dependencies) { ['deploy'] }
589 590 591 592 593

        it { expect { subject }.to raise_error(GitlabCiYamlProcessor::ValidationError, 'test1 job: dependency deploy is not defined in prior stages') }
      end
    end

594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
    describe "Hidden jobs" do
      let(:config) do
        YAML.dump({
                    '.hidden_job' => { script: 'test' },
                    'normal_job' => { script: 'test' }
                  })
      end

      let(:config_processor) { GitlabCiYamlProcessor.new(config) }

      subject { config_processor.builds_for_stage_and_ref("test", "master") }

      it "doesn't create jobs that starts with dot" do
        expect(subject.size).to eq(1)
        expect(subject.first).to eq({
          except: nil,
          stage: "test",
          stage_idx: 1,
          name: :normal_job,
          only: nil,
614
          commands: "test",
615 616 617 618 619 620 621 622
          tag_list: [],
          options: {},
          when: "on_success",
          allow_failure: false
        })
      end
    end

623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640
    describe "YAML Alias/Anchor" do
      it "is correctly supported for jobs" do
        config = <<EOT
job1: &JOBTMPL
  script: execute-script-for-job

job2: *JOBTMPL
EOT

        config_processor = GitlabCiYamlProcessor.new(config)

        expect(config_processor.builds_for_stage_and_ref("test", "master").size).to eq(2)
        expect(config_processor.builds_for_stage_and_ref("test", "master").first).to eq({
          except: nil,
          stage: "test",
          stage_idx: 1,
          name: :job1,
          only: nil,
641
          commands: "execute-script-for-job",
642 643 644 645 646 647 648 649 650 651 652
          tag_list: [],
          options: {},
          when: "on_success",
          allow_failure: false
        })
        expect(config_processor.builds_for_stage_and_ref("test", "master").second).to eq({
          except: nil,
          stage: "test",
          stage_idx: 1,
          name: :job2,
          only: nil,
653
          commands: "execute-script-for-job",
654 655 656 657 658 659 660 661
          tag_list: [],
          options: {},
          when: "on_success",
          allow_failure: false
        })
      end
    end

Valery Sizov committed
662
    describe "Error handling" do
663 664 665 666
      it "fails to parse YAML" do
        expect{GitlabCiYamlProcessor.new("invalid: yaml: test")}.to raise_error(Psych::SyntaxError)
      end

Valery Sizov committed
667
      it "indicates that object is invalid" do
668
        expect{GitlabCiYamlProcessor.new("invalid_yaml")}.to raise_error(GitlabCiYamlProcessor::ValidationError)
Valery Sizov committed
669 670 671 672 673
      end

      it "returns errors if tags parameter is invalid" do
        config = YAML.dump({ rspec: { script: "test", tags: "mysql" } })
        expect do
674
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
675 676 677 678 679 680
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: tags parameter should be an array of strings")
      end

      it "returns errors if before_script parameter is invalid" do
        config = YAML.dump({ before_script: "bundle update", rspec: { script: "test" } })
        expect do
681
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
682 683 684
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "before_script should be an array of strings")
      end

685 686 687 688 689 690 691
      it "returns errors if job before_script parameter is not an array of strings" do
        config = YAML.dump({ rspec: { script: "test", before_script: [10, "test"] } })
        expect do
          GitlabCiYamlProcessor.new(config, path)
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: before_script should be an array of strings")
      end

692 693 694 695 696 697 698
      it "returns errors if finally_script parameter is invalid" do
        config = YAML.dump({ finally_script: "bundle update", rspec: { script: "test" } })
        expect do
          GitlabCiYamlProcessor.new(config, path)
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "finally_script should be an array of strings")
      end

699 700 701 702 703 704 705
      it "returns errors if job finally_script parameter is not an array of strings" do
        config = YAML.dump({ rspec: { script: "test", finally_script: [10, "test"] } })
        expect do
          GitlabCiYamlProcessor.new(config, path)
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: finally_script should be an array of strings")
      end

Valery Sizov committed
706 707 708
      it "returns errors if image parameter is invalid" do
        config = YAML.dump({ image: ["test"], rspec: { script: "test" } })
        expect do
709
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
710 711 712
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "image should be a string")
      end

713 714 715
      it "returns errors if job name is blank" do
        config = YAML.dump({ '' => { script: "test" } })
        expect do
716
          GitlabCiYamlProcessor.new(config, path)
717 718 719 720 721 722
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "job name should be non-empty string")
      end

      it "returns errors if job name is non-string" do
        config = YAML.dump({ 10 => { script: "test" } })
        expect do
723
          GitlabCiYamlProcessor.new(config, path)
724 725 726
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "job name should be non-empty string")
      end

Valery Sizov committed
727 728 729
      it "returns errors if job image parameter is invalid" do
        config = YAML.dump({ rspec: { script: "test", image: ["test"] } })
        expect do
730
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
731 732 733 734 735 736
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: image should be a string")
      end

      it "returns errors if services parameter is not an array" do
        config = YAML.dump({ services: "test", rspec: { script: "test" } })
        expect do
737
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
738 739 740 741 742 743
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "services should be an array of strings")
      end

      it "returns errors if services parameter is not an array of strings" do
        config = YAML.dump({ services: [10, "test"], rspec: { script: "test" } })
        expect do
744
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
745 746 747 748 749 750
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "services should be an array of strings")
      end

      it "returns errors if job services parameter is not an array" do
        config = YAML.dump({ rspec: { script: "test", services: "test" } })
        expect do
751
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
752 753 754 755 756 757
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: services should be an array of strings")
      end

      it "returns errors if job services parameter is not an array of strings" do
        config = YAML.dump({ rspec: { script: "test", services: [10, "test"] } })
        expect do
758
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
759 760 761 762 763 764
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: services should be an array of strings")
      end

      it "returns errors if there are unknown parameters" do
        config = YAML.dump({ extra: "bundle update" })
        expect do
765
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
766 767 768 769 770 771
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "Unknown parameter: extra")
      end

      it "returns errors if there are unknown parameters that are hashes, but doesn't have a script" do
        config = YAML.dump({ extra: { services: "test" } })
        expect do
772
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
773 774 775
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "Unknown parameter: extra")
      end

776
      it "returns errors if there are no jobs defined" do
Valery Sizov committed
777 778
        config = YAML.dump({ before_script: ["bundle update"] })
        expect do
779
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
780 781 782 783 784 785
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "Please define at least one job")
      end

      it "returns errors if job allow_failure parameter is not an boolean" do
        config = YAML.dump({ rspec: { script: "test", allow_failure: "string" } })
        expect do
786
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
787 788 789 790
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: allow_failure parameter should be an boolean")
      end

      it "returns errors if job stage is not a string" do
791
        config = YAML.dump({ rspec: { script: "test", type: 1 } })
Valery Sizov committed
792
        expect do
793
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
794 795 796 797
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: stage parameter should be build, test, deploy")
      end

      it "returns errors if job stage is not a pre-defined stage" do
798
        config = YAML.dump({ rspec: { script: "test", type: "acceptance" } })
Valery Sizov committed
799
        expect do
800
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
801 802 803 804
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: stage parameter should be build, test, deploy")
      end

      it "returns errors if job stage is not a defined stage" do
805
        config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", type: "acceptance" } })
Valery Sizov committed
806
        expect do
807
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
808 809 810 811 812 813
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: stage parameter should be build, test")
      end

      it "returns errors if stages is not an array" do
        config = YAML.dump({ types: "test", rspec: { script: "test" } })
        expect do
814
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
815 816 817 818 819 820
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "stages should be an array of strings")
      end

      it "returns errors if stages is not an array of strings" do
        config = YAML.dump({ types: [true, "test"], rspec: { script: "test" } })
        expect do
821
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
822 823 824 825 826 827
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "stages should be an array of strings")
      end

      it "returns errors if variables is not a map" do
        config = YAML.dump({ variables: "test", rspec: { script: "test" } })
        expect do
828
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
829 830 831 832 833 834
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "variables should be a map of key-valued strings")
      end

      it "returns errors if variables is not a map of key-valued strings" do
        config = YAML.dump({ variables: { test: false }, rspec: { script: "test" } })
        expect do
835
          GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
836 837
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "variables should be a map of key-valued strings")
      end
838 839

      it "returns errors if job when is not on_success, on_failure or always" do
Kamil Trzcinski committed
840
        config = YAML.dump({ rspec: { script: "test", when: 1 } })
841
        expect do
842
          GitlabCiYamlProcessor.new(config, path)
843 844
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: when parameter should be on_success, on_failure or always")
      end
845

846 847 848 849 850 851 852
      it "returns errors if job artifacts:name is not an a string" do
        config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", artifacts: { name: 1 } } })
        expect do
          GitlabCiYamlProcessor.new(config)
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: artifacts:name parameter should be a string")
      end

853 854
      it "returns errors if job artifacts:untracked is not an array of strings" do
        config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", artifacts: { untracked: "string" } } })
855 856
        expect do
          GitlabCiYamlProcessor.new(config)
857 858 859 860 861 862 863 864
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: artifacts:untracked parameter should be an boolean")
      end

      it "returns errors if job artifacts:paths is not an array of strings" do
        config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", artifacts: { paths: "string" } } })
        expect do
          GitlabCiYamlProcessor.new(config)
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: artifacts:paths parameter should be an array of strings")
865
      end
866 867 868 869 870 871 872 873 874 875 876 877 878 879 880

      it "returns errors if cache:untracked is not an array of strings" do
        config = YAML.dump({ cache: { untracked: "string" }, rspec: { script: "test" } })
        expect do
          GitlabCiYamlProcessor.new(config)
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "cache:untracked parameter should be an boolean")
      end

      it "returns errors if cache:paths is not an array of strings" do
        config = YAML.dump({ cache: { paths: "string" }, rspec: { script: "test" } })
        expect do
          GitlabCiYamlProcessor.new(config)
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "cache:paths parameter should be an array of strings")
      end

881 882 883 884 885 886 887 888 889 890 891 892 893 894
      it "returns errors if cache:key is not a string" do
        config = YAML.dump({ cache: { key: 1 }, rspec: { script: "test" } })
        expect do
          GitlabCiYamlProcessor.new(config)
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "cache:key parameter should be a string")
      end

      it "returns errors if job cache:key is not an a string" do
        config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", cache: { key: 1 } } })
        expect do
          GitlabCiYamlProcessor.new(config)
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: cache:key parameter should be a string")
      end

895 896 897 898 899 900 901 902 903 904 905 906 907
      it "returns errors if job cache:untracked is not an array of strings" do
        config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", cache: { untracked: "string" } } })
        expect do
          GitlabCiYamlProcessor.new(config)
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: cache:untracked parameter should be an boolean")
      end

      it "returns errors if job cache:paths is not an array of strings" do
        config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", cache: { paths: "string" } } })
        expect do
          GitlabCiYamlProcessor.new(config)
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: cache:paths parameter should be an array of strings")
      end
908 909 910 911 912 913 914

      it "returns errors if job dependencies is not an array of strings" do
        config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", dependencies: "string" } })
        expect do
          GitlabCiYamlProcessor.new(config)
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: dependencies parameter should be an array of strings")
      end
915 916 917
    end
  end
end