BigW Consortium Gitlab

gitlab_ci_yaml_processor_spec.rb 47.8 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,
22
          name: "rspec",
23 24
          commands: "pwd\nrspec",
          tag_list: [],
Valery Sizov committed
25
          options: {},
Kamil Trzcinski committed
26
          allow_failure: false,
27 28
          when: "on_success",
          environment: nil,
29
          yaml_variables: []
Valery Sizov committed
30 31
        })
      end
32

33
      describe 'only' do
34 35 36 37 38
        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
        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
147
                               rspec: { script: "rspec", type: "test", only: ["master", "deploy"] },
148 149 150
                               staging: { script: "deploy", type: "deploy", only: ["master", "deploy"] },
                               production: { script: "deploy", type: "deploy", only: ["master@path", "deploy"] },
                             })
Valery Sizov committed
151

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

154
          expect(config_processor.builds_for_stage_and_ref("deploy", "deploy").size).to eq(2)
Kamil Trzcinski committed
155 156
          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)
157
        end
158 159 160 161 162 163 164

        context 'for invalid value' do
          let(:config) { { rspec: { script: "rspec", type: "test", only: only } } }
          let(:processor) { GitlabCiYamlProcessor.new(YAML.dump(config)) }

          shared_examples 'raises an error' do
            it do
165
              expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError, 'jobs:rspec:only config should be an array of strings or regexps')
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
            end
          end

          context 'when it is integer' do
            let(:only) { 1 }

            it_behaves_like 'raises an error'
          end

          context 'when it is an array of integers' do
            let(:only) { [1, 1] }

            it_behaves_like 'raises an error'
          end

          context 'when it is invalid regex' do
            let(:only) { ["/*invalid/"] }

            it_behaves_like 'raises an error'
          end
        end
Valery Sizov committed
187 188
      end

189
      describe 'except' do
190 191 192 193 194
        it "returns builds if except has another branch" do
          config = YAML.dump({
                               before_script: ["pwd"],
                               rspec: { script: "rspec", except: ["deploy"] }
                             })
Valery Sizov committed
195

196
          config_processor = GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
197

198 199 200 201 202 203 204 205 206 207 208 209 210
          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
211

212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
        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

256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
        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

278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
        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
303 304 305
                               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"] },
306 307
                             })

Kamil Trzcinski committed
308
          config_processor = GitlabCiYamlProcessor.new(config, 'fork')
309

Kamil Trzcinski committed
310 311 312
          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)
313 314
        end

315 316 317 318 319 320
        context 'for invalid value' do
          let(:config) { { rspec: { script: "rspec", except: except } } }
          let(:processor) { GitlabCiYamlProcessor.new(YAML.dump(config)) }

          shared_examples 'raises an error' do
            it do
321
              expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError, 'jobs:rspec:except config should be an array of strings or regexps')
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
            end
          end

          context 'when it is integer' do
            let(:except) { 1 }

            it_behaves_like 'raises an error'
          end

          context 'when it is an array of integers' do
            let(:except) { [1, 1] }

            it_behaves_like 'raises an error'
          end

          context 'when it is invalid regex' do
            let(:except) { ["/*invalid/"] }

            it_behaves_like 'raises an error'
          end
        end
      end
344
    end
345

346 347 348
    describe "Scripts handling" do
      let(:config_data) { YAML.dump(config) }
      let(:config_processor) { GitlabCiYamlProcessor.new(config_data, path) }
349

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

352 353
      describe "before_script" do
        context "in global context" do
Kamil Trzcinski committed
354
          let(:config) do
355 356 357 358
            {
              before_script: ["global script"],
              test: { script: ["script"] }
            }
Kamil Trzcinski committed
359
          end
360

361 362 363 364
          it "return commands with scripts concencaced" do
            expect(subject[:commands]).to eq("global script\nscript")
          end
        end
365

366
        context "overwritten in local context" do
Kamil Trzcinski committed
367
          let(:config) do
368 369 370 371
            {
              before_script: ["global script"],
              test: { before_script: ["local script"], script: ["script"] }
            }
Kamil Trzcinski committed
372
          end
373 374 375 376 377 378 379 380

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

      describe "script" do
Kamil Trzcinski committed
381
        let(:config) do
382 383 384
          {
            test: { script: ["script"] }
          }
Kamil Trzcinski committed
385
        end
386 387 388 389 390 391

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

392
      describe "after_script" do
393
        context "in global context" do
394
          let(:config) do
395
            {
396
              after_script: ["after_script"],
397 398
              test: { script: ["script"] }
            }
399
          end
400

401 402
          it "return after_script in options" do
            expect(subject[:options][:after_script]).to eq(["after_script"])
403 404
          end
        end
405 406

        context "overwritten in local context" do
Kamil Trzcinski committed
407
          let(:config) do
408
            {
409 410
              after_script: ["local after_script"],
              test: { after_script: ["local after_script"], script: ["script"] }
411
            }
Kamil Trzcinski committed
412
          end
413

414 415
          it "return after_script in options" do
            expect(subject[:options][:after_script]).to eq(["local after_script"])
416 417
          end
        end
418 419
      end
    end
420

Valery Sizov committed
421 422 423 424 425 426 427 428 429
    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" }
                           })

430
        config_processor = GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
431 432 433 434

        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({
          stage: "test",
435
          stage_idx: 1,
436
          name: "rspec",
437 438
          commands: "pwd\nrspec",
          tag_list: [],
Valery Sizov committed
439 440 441 442
          options: {
            image: "ruby:2.1",
            services: ["mysql"]
          },
443
          allow_failure: false,
444 445
          when: "on_success",
          environment: nil,
446
          yaml_variables: []
Valery Sizov committed
447 448 449 450 451 452 453 454 455 456 457
        })
      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" }
                           })

458
        config_processor = GitlabCiYamlProcessor.new(config, path)
Valery Sizov committed
459 460 461 462

        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({
          stage: "test",
463
          stage_idx: 1,
464
          name: "rspec",
465 466
          commands: "pwd\nrspec",
          tag_list: [],
Valery Sizov committed
467 468 469 470
          options: {
            image: "ruby:2.5",
            services: ["postgresql"]
          },
471
          allow_failure: false,
472 473
          when: "on_success",
          environment: nil,
474
          yaml_variables: []
Valery Sizov committed
475 476
        })
      end
477 478
    end

479
    describe 'Variables' do
480
      let(:config_processor) { GitlabCiYamlProcessor.new(YAML.dump(config), path) }
Valery Sizov committed
481

482 483 484 485 486 487 488 489
      subject { config_processor.builds.first[:yaml_variables] }

      context 'when global variables are defined' do
        let(:variables) do
          { VAR1: 'value1', VAR2: 'value2' }
        end
        let(:config) do
          {
490 491 492
            variables: variables,
            before_script: ['pwd'],
            rspec: { script: 'rspec' }
493 494
          }
        end
Valery Sizov committed
495

496 497 498 499 500 501 502
        it 'returns global variables' do
          expect(subject).to contain_exactly(
            { key: :VAR1, value: 'value1', public: true },
            { key: :VAR2, value: 'value2', public: true }
          )
        end
      end
503

504 505 506 507 508 509 510 511 512 513 514 515 516 517
      context 'when job and global variables are defined' do
        let(:global_variables) do
          { VAR1: 'global1', VAR3: 'global3' }
        end
        let(:job_variables) do
          { VAR1: 'value1', VAR2: 'value2' }
        end
        let(:config) do
          {
            before_script: ['pwd'],
            variables: global_variables,
            rspec: { script: 'rspec', variables: job_variables }
          }
        end
518

519 520 521 522 523 524
        it 'returns all unique variables' do
          expect(subject).to contain_exactly(
            { key: :VAR3, value: 'global3', public: true },
            { key: :VAR1, value: 'value1', public: true },
            { key: :VAR2, value: 'value2', public: true }
          )
525 526 527 528
        end
      end

      context 'when job variables are defined' do
529 530 531 532 533 534
        let(:config) do
          {
            before_script: ['pwd'],
            rspec: { script: 'rspec', variables: variables }
          }
        end
535

536 537 538 539
        context 'when syntax is correct' do
          let(:variables) do
            { VAR1: 'value1', VAR2: 'value2' }
          end
540

541 542 543 544 545
          it 'returns job variables' do
            expect(subject).to contain_exactly(
              { key: :VAR1, value: 'value1', public: true },
              { key: :VAR2, value: 'value2', public: true }
            )
546 547
          end
        end
548

549
        context 'when syntax is incorrect' do
550
          context 'when variables defined but invalid' do
551 552 553
            let(:variables) do
              [ :VAR1, 'value1', :VAR2, 'value2' ]
            end
554

555 556
            it 'raises error' do
              expect { subject }
557
                .to raise_error(GitlabCiYamlProcessor::ValidationError,
558
                                 /jobs:rspec:variables config should be a hash of key value pairs/)
559 560
            end
          end
561

562
          context 'when variables key defined but value not specified' do
563 564 565
            let(:variables) do
              nil
            end
566

567
            it 'returns empty array' do
568
              ##
569 570
              # When variables config is empty, we assume this is a valid
              # configuration, see issue #18775
571
              #
572 573
              expect(subject).to be_an_instance_of(Array)
              expect(subject).to be_empty
574
            end
575
          end
576
        end
Valery Sizov committed
577
      end
578 579

      context 'when job variables are not defined' do
580 581
        let(:config) do
          {
582 583
            before_script: ['pwd'],
            rspec: { script: 'rspec' }
584 585
          }
        end
586

587 588 589
        it 'returns empty array' do
          expect(subject).to be_an_instance_of(Array)
          expect(subject).to be_empty
590
        end
Valery Sizov committed
591
      end
592 593
    end

594 595 596 597 598 599 600
    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 }
                             })

601
          config_processor = GitlabCiYamlProcessor.new(config, path)
602

603 604 605 606 607 608 609
          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

610 611 612 613 614 615 616 617 618
    describe 'cache' do
      context 'when cache definition has unknown keys' do
        it 'raises relevant validation error' do
          config = YAML.dump(
            { cache: { untracked: true, invalid: 'key' },
              rspec: { script: 'rspec' } })

          expect { GitlabCiYamlProcessor.new(config) }.to raise_error(
            GitlabCiYamlProcessor::ValidationError,
619
            'cache config contains unknown keys: invalid'
620 621 622 623
          )
        end
      end

624 625
      it "returns cache when defined globally" do
        config = YAML.dump({
626
                             cache: { paths: ["logs/", "binaries/"], untracked: true, key: 'key' },
627 628 629 630 631 632 633 634 635 636 637
                             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,
638
          key: 'key',
639 640 641 642 643 644
        )
      end

      it "returns cache when defined in a job" do
        config = YAML.dump({
                             rspec: {
645
                               cache: { paths: ["logs/", "binaries/"], untracked: true, key: 'key' },
646 647 648 649 650 651 652 653 654 655
                               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,
656
          key: 'key',
657 658 659 660 661
        )
      end

      it "overwrite cache when defined for a job and globally" do
        config = YAML.dump({
662
                             cache: { paths: ["logs/", "binaries/"], untracked: true, key: 'global' },
663 664
                             rspec: {
                               script: "rspec",
665
                               cache: { paths: ["test/"], untracked: false, key: 'local' },
666 667 668 669 670 671 672 673 674
                             }
                           })

        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,
675
          key: 'local',
676 677 678 679
        )
      end
    end

680 681 682 683 684 685
    describe "Artifacts" do
      it "returns artifacts when defined" do
        config = YAML.dump({
                             image:         "ruby:2.1",
                             services:      ["mysql"],
                             before_script: ["pwd"],
686
                             rspec:         {
687 688 689 690 691 692
                               artifacts: {
                                 paths: ["logs/", "binaries/"],
                                 untracked: true,
                                 name: "custom_name",
                                 expire_in: "7d"
                               },
693 694
                               script: "rspec"
                             }
695 696 697 698 699 700 701 702
                           })

        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({
          stage: "test",
          stage_idx: 1,
703
          name: "rspec",
704 705 706 707 708
          commands: "pwd\nrspec",
          tag_list: [],
          options: {
            image: "ruby:2.1",
            services: ["mysql"],
709
            artifacts: {
710
              name: "custom_name",
711
              paths: ["logs/", "binaries/"],
712 713
              untracked: true,
              expire_in: "7d"
714
            }
715 716
          },
          when: "on_success",
717 718
          allow_failure: false,
          environment: nil,
719
          yaml_variables: []
720 721
        })
      end
722

Kamil Trzcinski committed
723
      %w[on_success on_failure always].each do |when_state|
724 725 726 727 728 729 730 731 732
        it "returns artifacts for when #{when_state}  defined" do
          config = YAML.dump({
                               rspec: {
                                 script: "rspec",
                                 artifacts: { paths: ["logs/", "binaries/"], when: when_state }
                               }
                             })

          config_processor = GitlabCiYamlProcessor.new(config, path)
Kamil Trzcinski committed
733

734 735 736 737 738
          builds = config_processor.builds_for_stage_and_ref("test", "master")
          expect(builds.size).to eq(1)
          expect(builds.first[:options][:artifacts][:when]).to eq(when_state)
        end
      end
739 740
    end

741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756
    describe '#environment' do
      let(:config) do
        {
          deploy_to_production: { stage: 'deploy', script: 'test', environment: environment }
        }
      end

      let(:processor) { GitlabCiYamlProcessor.new(YAML.dump(config)) }
      let(:builds) { processor.builds_for_stage_and_ref('deploy', 'master') }

      context 'when a production environment is specified' do
        let(:environment) { 'production' }

        it 'does return production' do
          expect(builds.size).to eq(1)
          expect(builds.first[:environment]).to eq(environment)
757 758 759 760 761 762 763 764 765 766 767 768 769
          expect(builds.first[:options]).to include(environment: { name: environment })
        end
      end

      context 'when hash is specified' do
        let(:environment) do
          { name: 'production',
            url: 'http://production.gitlab.com' }
        end

        it 'does return production and URL' do
          expect(builds.size).to eq(1)
          expect(builds.first[:environment]).to eq(environment[:name])
770
          expect(builds.first[:options]).to include(environment: environment)
771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786
        end
      end

      context 'when no environment is specified' do
        let(:environment) { nil }

        it 'does return nil environment' do
          expect(builds.size).to eq(1)
          expect(builds.first[:environment]).to be_nil
        end
      end

      context 'is not a string' do
        let(:environment) { 1 }

        it 'raises error' do
787 788
          expect { builds }.to raise_error(
            'jobs:deploy_to_production:environment config should be a hash or a string')
789 790 791 792
        end
      end

      context 'is not a valid string' do
793
        let(:environment) { 'production:staging' }
794 795

        it 'raises error' do
796
          expect { builds }.to raise_error("jobs:deploy_to_production:environment name #{Gitlab::Regex.environment_name_regex_message}")
797 798 799 800
        end
      end
    end

801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816
    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) { }

817
        it { expect { subject }.not_to raise_error }
818 819 820
      end

      context 'dependencies to builds' do
821
        let(:dependencies) { ['build1', 'build2'] }
822

823
        it { expect { subject }.not_to raise_error }
824 825
      end

826 827 828
      context 'dependencies to builds defined as symbols' do
        let(:dependencies) { [:build1, :build2] }

829
        it { expect { subject }.not_to raise_error }
830 831
      end

832
      context 'undefined dependency' do
833
        let(:dependencies) { ['undefined'] }
834 835 836 837 838

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

      context 'dependencies to deploy' do
839
        let(:dependencies) { ['deploy'] }
840 841 842 843 844

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

845
    describe "Hidden jobs" do
846 847 848 849
      let(:config_processor) { GitlabCiYamlProcessor.new(config) }
      subject { config_processor.builds_for_stage_and_ref("test", "master") }

      shared_examples 'hidden_job_handling' do
Tomasz Maczukin committed
850
        it "doesn't create jobs that start with dot" do
851 852 853 854
          expect(subject.size).to eq(1)
          expect(subject.first).to eq({
            stage: "test",
            stage_idx: 1,
855
            name: "normal_job",
856 857 858 859
            commands: "test",
            tag_list: [],
            options: {},
            when: "on_success",
860 861
            allow_failure: false,
            environment: nil,
862
            yaml_variables: []
863 864
          })
        end
865 866
      end

Tomasz Maczukin committed
867
      context 'when hidden job have a script definition' do
868 869 870 871 872 873
        let(:config) do
          YAML.dump({
                      '.hidden_job' => { image: 'ruby:2.1', script: 'test' },
                      'normal_job' => { script: 'test' }
                    })
        end
874

875 876
        it_behaves_like 'hidden_job_handling'
      end
877

Tomasz Maczukin committed
878
      context "when hidden job doesn't have a script definition" do
879 880 881 882 883 884 885 886
        let(:config) do
          YAML.dump({
                      '.hidden_job' => { image: 'ruby:2.1' },
                      'normal_job' => { script: 'test' }
                    })
        end

        it_behaves_like 'hidden_job_handling'
887 888 889
      end
    end

890
    describe "YAML Alias/Anchor" do
891 892 893 894 895 896 897 898 899
      let(:config_processor) { GitlabCiYamlProcessor.new(config) }
      subject { config_processor.builds_for_stage_and_ref("build", "master") }

      shared_examples 'job_templates_handling' do
        it "is correctly supported for jobs" do
          expect(subject.size).to eq(2)
          expect(subject.first).to eq({
            stage: "build",
            stage_idx: 0,
900
            name: "job1",
901 902 903 904
            commands: "execute-script-for-job",
            tag_list: [],
            options: {},
            when: "on_success",
905 906
            allow_failure: false,
            environment: nil,
907
            yaml_variables: []
908 909 910 911
          })
          expect(subject.second).to eq({
            stage: "build",
            stage_idx: 0,
912
            name: "job2",
913 914 915 916
            commands: "execute-script-for-job",
            tag_list: [],
            options: {},
            when: "on_success",
917 918
            allow_failure: false,
            environment: nil,
919
            yaml_variables: []
920 921 922 923
          })
        end
      end

Tomasz Maczukin committed
924
      context 'when template is a job' do
Tomasz Maczukin committed
925
        let(:config) do
926
          <<EOT
927
job1: &JOBTMPL
928
  stage: build
929 930 931 932
  script: execute-script-for-job

job2: *JOBTMPL
EOT
933
        end
934

935 936
        it_behaves_like 'job_templates_handling'
      end
937

Tomasz Maczukin committed
938
      context 'when template is a hidden job' do
Tomasz Maczukin committed
939
        let(:config) do
940 941 942 943 944 945 946 947 948 949 950 951 952 953
          <<EOT
.template: &JOBTMPL
  stage: build
  script: execute-script-for-job

job1: *JOBTMPL

job2: *JOBTMPL
EOT
        end

        it_behaves_like 'job_templates_handling'
      end

Tomasz Maczukin committed
954
      context 'when job adds its own keys to a template definition' do
Tomasz Maczukin committed
955
        let(:config) do
956 957 958 959 960 961 962 963 964 965 966 967 968 969 970
          <<EOT
.template: &JOBTMPL
  stage: build

job1:
  <<: *JOBTMPL
  script: execute-script-for-job

job2:
  <<: *JOBTMPL
  script: execute-script-for-job
EOT
        end

        it_behaves_like 'job_templates_handling'
971 972 973
      end
    end

Valery Sizov committed
974
    describe "Error handling" do
975 976 977 978
      it "fails to parse YAML" do
        expect{GitlabCiYamlProcessor.new("invalid: yaml: test")}.to raise_error(Psych::SyntaxError)
      end

Valery Sizov committed
979
      it "indicates that object is invalid" do
980
        expect{GitlabCiYamlProcessor.new("invalid_yaml")}.to raise_error(GitlabCiYamlProcessor::ValidationError)
Valery Sizov committed
981 982 983 984 985
      end

      it "returns errors if tags parameter is invalid" do
        config = YAML.dump({ rspec: { script: "test", tags: "mysql" } })
        expect do
986
          GitlabCiYamlProcessor.new(config, path)
987
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec tags should be an array of strings")
Valery Sizov committed
988 989 990 991 992
      end

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

997 998 999 1000
      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)
1001
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:before_script config should be an array of strings")
1002 1003
      end

1004 1005
      it "returns errors if after_script parameter is invalid" do
        config = YAML.dump({ after_script: "bundle update", rspec: { script: "test" } })
1006 1007
        expect do
          GitlabCiYamlProcessor.new(config, path)
1008
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "after_script config should be an array of strings")
1009 1010
      end

1011 1012
      it "returns errors if job after_script parameter is not an array of strings" do
        config = YAML.dump({ rspec: { script: "test", after_script: [10, "test"] } })
1013 1014
        expect do
          GitlabCiYamlProcessor.new(config, path)
1015
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:after_script config should be an array of strings")
1016 1017
      end

Valery Sizov committed
1018 1019 1020
      it "returns errors if image parameter is invalid" do
        config = YAML.dump({ image: ["test"], rspec: { script: "test" } })
        expect do
1021
          GitlabCiYamlProcessor.new(config, path)
1022
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "image config should be a string")
Valery Sizov committed
1023 1024
      end

1025 1026 1027
      it "returns errors if job name is blank" do
        config = YAML.dump({ '' => { script: "test" } })
        expect do
1028
          GitlabCiYamlProcessor.new(config, path)
1029
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:job name can't be blank")
1030 1031 1032 1033 1034
      end

      it "returns errors if job name is non-string" do
        config = YAML.dump({ 10 => { script: "test" } })
        expect do
1035
          GitlabCiYamlProcessor.new(config, path)
1036
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:10 name should be a symbol")
1037 1038
      end

Valery Sizov committed
1039 1040 1041
      it "returns errors if job image parameter is invalid" do
        config = YAML.dump({ rspec: { script: "test", image: ["test"] } })
        expect do
1042
          GitlabCiYamlProcessor.new(config, path)
1043
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:image config should be a string")
Valery Sizov committed
1044 1045 1046 1047 1048
      end

      it "returns errors if services parameter is not an array" do
        config = YAML.dump({ services: "test", rspec: { script: "test" } })
        expect do
1049
          GitlabCiYamlProcessor.new(config, path)
1050
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "services config should be an array of strings")
Valery Sizov committed
1051 1052 1053 1054 1055
      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
1056
          GitlabCiYamlProcessor.new(config, path)
1057
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "services config should be an array of strings")
Valery Sizov committed
1058 1059 1060 1061 1062
      end

      it "returns errors if job services parameter is not an array" do
        config = YAML.dump({ rspec: { script: "test", services: "test" } })
        expect do
1063
          GitlabCiYamlProcessor.new(config, path)
1064
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:services config should be an array of strings")
Valery Sizov committed
1065 1066 1067 1068 1069
      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
1070
          GitlabCiYamlProcessor.new(config, path)
1071
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:services config should be an array of strings")
Valery Sizov committed
1072 1073
      end

1074
      it "returns error if job configuration is invalid" do
Valery Sizov committed
1075 1076
        config = YAML.dump({ extra: "bundle update" })
        expect do
1077
          GitlabCiYamlProcessor.new(config, path)
1078
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:extra config should be a hash")
Valery Sizov committed
1079 1080 1081 1082 1083
      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
1084
          GitlabCiYamlProcessor.new(config, path)
1085
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:extra:services config should be an array of strings")
Valery Sizov committed
1086 1087
      end

1088
      it "returns errors if there are no jobs defined" do
Valery Sizov committed
1089 1090
        config = YAML.dump({ before_script: ["bundle update"] })
        expect do
1091
          GitlabCiYamlProcessor.new(config, path)
1092 1093 1094 1095
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs config should contain at least one visible job")
      end

      it "returns errors if there are no visible jobs defined" do
1096
        config = YAML.dump({ before_script: ["bundle update"], '.hidden'.to_sym => { script: 'ls' } })
1097 1098 1099
        expect do
          GitlabCiYamlProcessor.new(config, path)
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs config should contain at least one visible job")
Valery Sizov committed
1100 1101 1102 1103 1104
      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
1105
          GitlabCiYamlProcessor.new(config, path)
1106
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec allow failure should be a boolean value")
Valery Sizov committed
1107 1108 1109
      end

      it "returns errors if job stage is not a string" do
1110
        config = YAML.dump({ rspec: { script: "test", type: 1 } })
Valery Sizov committed
1111
        expect do
1112
          GitlabCiYamlProcessor.new(config, path)
1113
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:type config should be a string")
Valery Sizov committed
1114 1115 1116
      end

      it "returns errors if job stage is not a pre-defined stage" do
1117
        config = YAML.dump({ rspec: { script: "test", type: "acceptance" } })
Valery Sizov committed
1118
        expect do
1119
          GitlabCiYamlProcessor.new(config, path)
1120
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: stage parameter should be build, test, deploy")
Valery Sizov committed
1121 1122 1123
      end

      it "returns errors if job stage is not a defined stage" do
1124
        config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", type: "acceptance" } })
Valery Sizov committed
1125
        expect do
1126
          GitlabCiYamlProcessor.new(config, path)
1127
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: stage parameter should be build, test")
Valery Sizov committed
1128 1129 1130
      end

      it "returns errors if stages is not an array" do
1131
        config = YAML.dump({ stages: "test", rspec: { script: "test" } })
Valery Sizov committed
1132
        expect do
1133
          GitlabCiYamlProcessor.new(config, path)
1134
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "stages config should be an array of strings")
Valery Sizov committed
1135 1136 1137
      end

      it "returns errors if stages is not an array of strings" do
1138
        config = YAML.dump({ stages: [true, "test"], rspec: { script: "test" } })
Valery Sizov committed
1139
        expect do
1140
          GitlabCiYamlProcessor.new(config, path)
1141
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "stages config should be an array of strings")
Valery Sizov committed
1142 1143 1144 1145 1146
      end

      it "returns errors if variables is not a map" do
        config = YAML.dump({ variables: "test", rspec: { script: "test" } })
        expect do
1147
          GitlabCiYamlProcessor.new(config, path)
1148
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "variables config should be a hash of key value pairs")
Valery Sizov committed
1149 1150
      end

1151
      it "returns errors if variables is not a map of key-value strings" do
Valery Sizov committed
1152 1153
        config = YAML.dump({ variables: { test: false }, rspec: { script: "test" } })
        expect do
1154
          GitlabCiYamlProcessor.new(config, path)
1155
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "variables config should be a hash of key value pairs")
Valery Sizov committed
1156
      end
1157 1158

      it "returns errors if job when is not on_success, on_failure or always" do
Kamil Trzcinski committed
1159
        config = YAML.dump({ rspec: { script: "test", when: 1 } })
1160
        expect do
1161
          GitlabCiYamlProcessor.new(config, path)
1162
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec when should be on_success, on_failure, always or manual")
1163
      end
1164

1165 1166 1167 1168
      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)
1169
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:artifacts name should be a string")
1170 1171
      end

1172 1173 1174 1175
      it "returns errors if job artifacts:when is not an a predefined value" do
        config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", artifacts: { when: 1 } } })
        expect do
          GitlabCiYamlProcessor.new(config)
1176
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:artifacts when should be on_success, on_failure or always")
1177 1178
      end

1179 1180 1181 1182
      it "returns errors if job artifacts:expire_in is not an a string" do
        config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", artifacts: { expire_in: 1 } } })
        expect do
          GitlabCiYamlProcessor.new(config)
1183
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:artifacts expire in should be a duration")
1184 1185 1186 1187 1188 1189
      end

      it "returns errors if job artifacts:expire_in is not an a valid duration" do
        config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", artifacts: { expire_in: "7 elephants" } } })
        expect do
          GitlabCiYamlProcessor.new(config)
1190
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:artifacts expire in should be a duration")
1191 1192
      end

1193 1194
      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" } } })
1195 1196
        expect do
          GitlabCiYamlProcessor.new(config)
1197
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:artifacts untracked should be a boolean value")
1198 1199 1200 1201 1202 1203
      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)
1204
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:artifacts paths should be an array of strings")
1205
      end
1206 1207 1208 1209 1210

      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)
1211
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "cache:untracked config should be a boolean value")
1212 1213 1214 1215 1216 1217
      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)
1218
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "cache:paths config should be an array of strings")
1219 1220
      end

1221 1222 1223 1224
      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)
1225
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "cache:key config should be a string or symbol")
1226 1227 1228 1229 1230 1231
      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)
1232
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:cache:key config should be a string or symbol")
1233 1234
      end

1235 1236 1237 1238
      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)
1239
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:cache:untracked config should be a boolean value")
1240 1241 1242 1243 1244 1245
      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)
1246
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:cache:paths config should be an array of strings")
1247
      end
1248 1249 1250 1251 1252

      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)
1253
        end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec dependencies should be an array of strings")
1254
      end
1255
    end
1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267

    describe "Validate configuration templates" do
      templates = Dir.glob("#{Rails.root.join('vendor/gitlab-ci-yml')}/**/*.gitlab-ci.yml")

      templates.each do |file|
        it "does not return errors for #{file}" do
          file = File.read(file)

          expect { GitlabCiYamlProcessor.new(file) }.not_to raise_error
        end
      end
    end
1268

Katarzyna Kobierska committed
1269
    describe "#validation_message" do
Katarzyna Kobierska committed
1270 1271
      context "when the YAML could not be parsed" do
        it "returns an error about invalid configutaion" do
1272
          content = YAML.dump("invalid: yaml: test")
Katarzyna Kobierska committed
1273

Katarzyna Kobierska committed
1274 1275
          expect(GitlabCiYamlProcessor.validation_message(content))
            .to eq "Invalid configuration format"
1276
        end
Katarzyna Kobierska committed
1277
      end
1278

Katarzyna Kobierska committed
1279 1280
      context "when the tags parameter is invalid" do
        it "returns an error about invalid tags" do
1281
          content = YAML.dump({ rspec: { script: "test", tags: "mysql" } })
Katarzyna Kobierska committed
1282

Katarzyna Kobierska committed
1283 1284
          expect(GitlabCiYamlProcessor.validation_message(content))
            .to eq "jobs:rspec tags should be an array of strings"
Katarzyna Kobierska committed
1285 1286 1287
        end
      end

1288
      context "when YAML content is empty" do
Katarzyna Kobierska committed
1289
        it "returns an error about missing content" do
Katarzyna Kobierska committed
1290 1291
          expect(GitlabCiYamlProcessor.validation_message(''))
            .to eq "Please provide content of .gitlab-ci.yml"
1292
        end
Katarzyna Kobierska committed
1293
      end
1294

Katarzyna Kobierska committed
1295 1296
      context "when the YAML is valid" do
        it "does not return any errors" do
1297
          content = File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
Katarzyna Kobierska committed
1298 1299

          expect(GitlabCiYamlProcessor.validation_message(content)).to be_nil
1300 1301 1302
        end
      end
    end
1303 1304
  end
end