bridge_spec.rb 8.11 KB
Newer Older
1
2
# frozen_string_literal: true

3
require 'spec_helper'
4
5

describe EE::Gitlab::Ci::Config::Entry::Bridge do
6
7
8
9
10
11
12
13
14
15
  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
16
17
      %i[before_script after_script image services cache interruptible timeout
         retry tags]
18
19
20
    end
  end

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

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

28
      it { is_expected.to be_falsey }
29
30
    end

31
32
33
34
    context 'when config is a regular job' do
      let(:name) { :my_trigger }
      let(:config) do
        { script: 'ls -al' }
35
36
      end

37
      it { is_expected.to be_falsey }
drew's avatar
drew committed
38
39
40
41
42
43
44
45
46
47
48

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

        it { is_expected.to be_falsey }
      end
49
50
    end

51
52
53
54
55
56
57
    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 }
drew's avatar
drew committed
58
59
60
61
62
63
64
65
66
67
68

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

        it { is_expected.to be_truthy }
      end
69
70
    end

71
72
73
74
    context 'when config is a hidden job' do
      let(:name) { '.my_trigger' }
      let(:config) do
        { trigger: 'other-project' }
75
      end
76
77

      it { is_expected.to be_falsey }
78
79
80
    end
  end

81
82
83
  describe '.new' do
    before do
      subject.compose!
84
85
    end

drew's avatar
drew committed
86
87
88
89
90
91
92
93
94
95
    let(:base_config) do
      {
        trigger: { project: 'some/project', branch: 'feature' },
        needs: { pipeline: 'other/project' },
        extends: '.some-key',
        stage: 'deploy',
        variables: { VARIABLE: '123' }
      }
    end

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

99
100
101
      describe '#valid?' do
        it { is_expected.to be_valid }
      end
102

103
104
      describe '#value' do
        it 'is returns a bridge job configuration' do
105
          expect(subject.value).to eq(name: :my_bridge,
106
107
108
109
110
111
                                      trigger: { project: 'some/project' },
                                      ignore: false,
                                      stage: 'test',
                                      only: { refs: %w[branches tags] })
        end
      end
112
113
    end

114
115
    context 'when needs pipeline config is a non-empty string' do
      let(:config) { { needs: { pipeline: 'some/project' } } }
116
117
118
119
120
121
122
123

      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,
124
                                      needs: { bridge: [{ pipeline: 'some/project' }] },
125
126
127
128
129
130
131
                                      ignore: false,
                                      stage: 'test',
                                      only: { refs: %w[branches tags] })
        end
      end
    end

132
133
134
135
136
137
138
139
140
141
142
    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
143
          expect(subject.value).to eq(name: :my_bridge,
144
                                      trigger: { project: 'some/project',
145
                                                 branch: 'feature' },
146
147
148
149
                                      ignore: false,
                                      stage: 'test',
                                      only: { refs: %w[branches tags] })
        end
150
151
152
      end
    end

drew's avatar
drew committed
153
    context 'when bridge configuration contains trigger, needs, when, extends, stage, only, except, and variables' do
154
      let(:config) do
drew's avatar
drew committed
155
        base_config.merge({
156
157
          when: 'always',
          only: { variables: %w[$SOMEVARIABLE] },
drew's avatar
drew committed
158
159
          except: { refs: %w[feature] }
        })
160
      end
161

162
      it { is_expected.to be_valid }
163
164
    end

drew's avatar
drew committed
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
    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

204
205
206
207
208
209
210
211
212
    context 'when trigger config is nil' do
      let(:config) { { trigger: nil } }

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

      describe '#errors' do
        it 'is returns an error about empty trigger config' do
213
          expect(subject.errors.first).to eq('bridge config should contain either a trigger or a needs:pipeline')
214
215
216
217
218
219
220
221
222
223
224
225
226
        end
      end
    end

    context 'when upstream config is nil' do
      let(:config) { { needs: nil } }

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

      describe '#errors' do
        it 'is returns an error about empty upstream config' do
227
          expect(subject.errors.first).to eq('bridge config should contain either a trigger or a needs:pipeline')
228
        end
229
230
231
      end
    end

232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
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
275
    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 has bridge and job needs' do
      let(:config) do
        {
          trigger: 'other-project',
          needs: ['some_job', { pipeline: 'some/other_project' }]
        }
      end

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

    context 'when bridge has more than one valid bridge needs' do
      let(:config) do
        {
          trigger: 'other-project',
          needs: [{ pipeline: 'some/project' }, { pipeline: 'some/other_project' }]
        }
      end

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

      describe '#errors' do
        it 'returns an error about too many bridge needs' do
          expect(subject.errors).to contain_exactly('bridge config should contain at most one bridge need')
        end
      end
    end

276
277
278
279
280
281
    context 'when bridge config contains unknown keys' do
      let(:config) { { unknown: 123 } }

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

283
284
285
286
287
288
      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
289
290
    end

291
292
293
294
295
296
297
298
299
300
301
302
    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
303
304
305
306
      end
    end
  end
end