bridge_spec.rb 6.05 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
# frozen_string_literal: true

require 'spec_helper'

describe Gitlab::Ci::Config::Entry::Bridge do
  subject { described_class.new(config, name: :my_bridge) }

  it_behaves_like 'with inheritable CI config' do
    let(:inheritable_key) { 'default' }
    let(:inheritable_class) { Gitlab::Ci::Config::Entry::Default }

    # These are entries defined in Default
    # that we know that we don't want to inherit
    # as they do not have sense in context of Bridge
    let(:ignored_inheritable_columns) do
      %i[before_script after_script image services cache interruptible timeout
         retry tags artifacts]
    end
  end

  describe '.matching?' do
    subject { described_class.matching?(name, config) }

    context 'when config is not a hash' do
      let(:name) { :my_trigger }
      let(:config) { 'string' }

      it { is_expected.to be_falsey }
    end

    context 'when config is a regular job' do
      let(:name) { :my_trigger }
      let(:config) do
        { script: 'ls -al' }
      end

      it { is_expected.to be_falsey }

      context 'with rules' do
        let(:config) do
          {
            script: 'ls -al',
            rules: [{ if: '$VAR == "value"', when: 'always' }]
          }
        end

        it { is_expected.to be_falsey }
      end
    end

    context 'when config is a bridge job' do
      let(:name) { :my_trigger }
      let(:config) do
        { trigger: 'other-project' }
      end

      it { is_expected.to be_truthy }

      context 'with rules' do
        let(:config) do
          {
            trigger: 'other-project',
            rules: [{ if: '$VAR == "value"', when: 'always' }]
          }
        end

        it { is_expected.to be_truthy }
      end
    end

    context 'when config is a hidden job' do
      let(:name) { '.my_trigger' }
      let(:config) do
        { trigger: 'other-project' }
      end

      it { is_expected.to be_falsey }
    end
  end

  describe '.new' do
    before do
      subject.compose!
    end

    let(:base_config) do
      {
        trigger: { project: 'some/project', branch: 'feature' },
        extends: '.some-key',
        stage: 'deploy',
        variables: { VARIABLE: '123' }
      }
    end

    context 'when trigger config is a non-empty string' do
      let(:config) { { trigger: 'some/project' } }

      describe '#valid?' do
        it { is_expected.to be_valid }
      end

      describe '#value' do
        it 'is returns a bridge job configuration' do
          expect(subject.value).to eq(name: :my_bridge,
                                      trigger: { project: 'some/project' },
                                      ignore: false,
                                      stage: 'test',
108
                                      only: { refs: %w[branches tags] },
109
                                      variables: {},
110
                                      scheduling_type: :stage)
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
        end
      end
    end

    context 'when bridge trigger is a hash' do
      let(:config) do
        { trigger: { project: 'some/project', branch: 'feature' } }
      end

      describe '#valid?' do
        it { is_expected.to be_valid }
      end

      describe '#value' do
        it 'is returns a bridge job configuration hash' do
          expect(subject.value).to eq(name: :my_bridge,
                                      trigger: { project: 'some/project',
                                                 branch: 'feature' },
                                      ignore: false,
                                      stage: 'test',
131
                                      only: { refs: %w[branches tags] },
132
                                      variables: {},
133
                                      scheduling_type: :stage)
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 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 228 229 230 231
        end
      end
    end

    context 'when bridge configuration contains trigger, when, extends, stage, only, except, and variables' do
      let(:config) do
        base_config.merge({
          when: 'always',
          only: { variables: %w[$SOMEVARIABLE] },
          except: { refs: %w[feature] }
        })
      end

      it { is_expected.to be_valid }
    end

    context 'when bridge configuration uses rules' do
      let(:config) { base_config.merge({ rules: [{ if: '$VAR == null', when: 'never' }] }) }

      it { is_expected.to be_valid }
    end

    context 'when bridge configuration uses rules with job:when' do
      let(:config) do
        base_config.merge({
          when: 'always',
          rules: [{ if: '$VAR == null', when: 'never' }]
        })
      end

      it { is_expected.not_to be_valid }
    end

    context 'when bridge configuration uses rules with only' do
      let(:config) do
        base_config.merge({
          only: { variables: %w[$SOMEVARIABLE] },
          rules: [{ if: '$VAR == null', when: 'never' }]
        })
      end

      it { is_expected.not_to be_valid }
    end

    context 'when bridge configuration uses rules with except' do
      let(:config) do
        base_config.merge({
          except: { refs: %w[feature] },
          rules: [{ if: '$VAR == null', when: 'never' }]
        })
      end

      it { is_expected.not_to be_valid }
    end

    context 'when bridge has only job needs' do
      let(:config) do
        {
          needs: ['some_job']
        }
      end

      describe '#valid?' do
        it { is_expected.not_to be_valid }
      end
    end

    context 'when bridge config contains unknown keys' do
      let(:config) { { unknown: 123 } }

      describe '#valid?' do
        it { is_expected.not_to be_valid }
      end

      describe '#errors' do
        it 'is returns an error about unknown config key' do
          expect(subject.errors.first)
            .to match /config contains unknown keys: unknown/
        end
      end
    end

    context 'when bridge config contains build-specific attributes' do
      let(:config) { { script: 'something' } }

      describe '#valid?' do
        it { is_expected.not_to be_valid }
      end

      describe '#errors' do
        it 'returns an error message' do
          expect(subject.errors.first)
            .to match /contains unknown keys: script/
        end
      end
    end
  end
end