update_service_spec.rb 11.8 KB
Newer Older
1
2
require 'spec_helper'

3
describe Projects::UpdateService do
4
5
  include ProjectForksHelper

6
  let(:user) { create(:user) }
7
  let(:project) do
8
    create(:project, creator: user, namespace: user.namespace)
9
10
  end

11
12
13
  describe '#execute' do
    let(:gitlab_shell) { Gitlab::Shell.new }
    let(:admin) { create(:admin) }
14

15
    context 'when changing visibility level' do
16
17
      context 'when visibility_level is INTERNAL' do
        it 'updates the project to internal' do
18
19
          expect(TodosDestroyer::ProjectPrivateWorker).not_to receive(:perform_in)

20
          result = update_project(project, user, visibility_level: Gitlab::VisibilityLevel::INTERNAL)
21

22
23
          expect(result).to eq({ status: :success })
          expect(project).to be_internal
24
25
26
        end
      end

27
      context 'when visibility_level is PUBLIC' do
28
        it 'updates the project to public' do
29
30
          expect(TodosDestroyer::ProjectPrivateWorker).not_to receive(:perform_in)

31
          result = update_project(project, user, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
32

33
34
35
36
          expect(result).to eq({ status: :success })
          expect(project).to be_public
        end
      end
37

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
      context 'when visibility_level is PRIVATE' do
        before do
          project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
        end

        it 'updates the project to private' do
          expect(TodosDestroyer::ProjectPrivateWorker).to receive(:perform_in).with(1.hour, project.id)

          result = update_project(project, user, visibility_level: Gitlab::VisibilityLevel::PRIVATE)

          expect(result).to eq({ status: :success })
          expect(project).to be_private
        end
      end

53
54
55
      context 'when visibility levels are restricted to PUBLIC only' do
        before do
          stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
56
57
        end

58
59
60
        context 'when visibility_level is INTERNAL' do
          it 'updates the project to internal' do
            result = update_project(project, user, visibility_level: Gitlab::VisibilityLevel::INTERNAL)
61

62
            expect(result).to eq({ status: :success })
63
            expect(project).to be_internal
64
          end
65
        end
66

67
68
69
        context 'when visibility_level is PUBLIC' do
          it 'does not update the project to public' do
            result = update_project(project, user, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
70

71
72
73
74
75
76
77
            expect(result).to eq({ status: :error, message: 'New visibility level not allowed!' })
            expect(project).to be_private
          end

          context 'when updated by an admin' do
            it 'updates the project to public' do
              result = update_project(project, admin, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
78

79
80
81
82
83
              expect(result).to eq({ status: :success })
              expect(project).to be_public
            end
          end
        end
84
85
      end

86
      context 'when project visibility is higher than parent group' do
87
88
89
90
91
92
93
94
        let(:group) { create(:group, visibility_level: Gitlab::VisibilityLevel::INTERNAL) }

        before do
          project.update(namespace: group, visibility_level: group.visibility_level)
        end

        it 'does not update project visibility level' do
          result = update_project(project, admin, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
95

96
97
98
          expect(result).to eq({ status: :error, message: 'Visibility level public is not allowed in a internal group.' })
          expect(project.reload).to be_internal
        end
99
100
      end
    end
101

102
103
104
    describe 'when updating project that has forks' do
      let(:project) { create(:project, :internal) }
      let(:forked_project) { fork_project(project) }
105

106
107
      it 'updates forks visibility level when parent set to more restrictive' do
        opts = { visibility_level: Gitlab::VisibilityLevel::PRIVATE }
108

109
110
        expect(project).to be_internal
        expect(forked_project).to be_internal
111

112
        expect(update_project(project, admin, opts)).to eq({ status: :success })
113

114
115
116
        expect(project).to be_private
        expect(forked_project.reload).to be_private
      end
117

118
119
      it 'does not update forks visibility level when parent set to less restrictive' do
        opts = { visibility_level: Gitlab::VisibilityLevel::PUBLIC }
120

121
122
        expect(project).to be_internal
        expect(forked_project).to be_internal
123

124
        expect(update_project(project, admin, opts)).to eq({ status: :success })
125

126
127
128
        expect(project).to be_public
        expect(forked_project.reload).to be_internal
      end
129
130
    end

131
132
    context 'when updating a default branch' do
      let(:project) { create(:project, :repository) }
133

134
135
      it 'changes a default branch' do
        update_project(project, admin, default_branch: 'feature')
136

137
138
        expect(Project.find(project.id).default_branch).to eq 'feature'
      end
139

140
141
142
      it 'does not change a default branch' do
        # The branch 'unexisted-branch' does not exist.
        update_project(project, admin, default_branch: 'unexisted-branch')
143

144
145
        expect(Project.find(project.id).default_branch).to eq 'master'
      end
146
    end
147

148
149
    context 'when we update project but not enabling a wiki' do
      it 'does not try to create an empty wiki' do
150
        Gitlab::Shell.new.rm_directory(project.repository_storage, project.wiki.path)
151
152
153
154
155
156

        result = update_project(project, user, { name: 'test1' })

        expect(result).to eq({ status: :success })
        expect(project.wiki_repository_exists?).to be false
      end
157
158
159
160
161
162
163
164
165

      it 'handles empty project feature attributes' do
        project.project_feature.update(wiki_access_level: ProjectFeature::DISABLED)

        result = update_project(project, user, { name: 'test1' })

        expect(result).to eq({ status: :success })
        expect(project.wiki_repository_exists?).to be false
      end
166
167
    end

168
169
170
    context 'when enabling a wiki' do
      it 'creates a wiki' do
        project.project_feature.update(wiki_access_level: ProjectFeature::DISABLED)
171
        Gitlab::Shell.new.rm_directory(project.repository_storage, project.wiki.path)
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190

        result = update_project(project, user, project_feature_attributes: { wiki_access_level: ProjectFeature::ENABLED })

        expect(result).to eq({ status: :success })
        expect(project.wiki_repository_exists?).to be true
        expect(project.wiki_enabled?).to be true
      end

      it 'logs an error and creates a metric when wiki can not be created' do
        project.project_feature.update(wiki_access_level: ProjectFeature::DISABLED)

        expect_any_instance_of(ProjectWiki).to receive(:wiki).and_raise(ProjectWiki::CouldNotCreateWikiError)
        expect_any_instance_of(described_class).to receive(:log_error).with("Could not create wiki for #{project.full_name}")
        expect(Gitlab::Metrics).to receive(:counter)

        update_project(project, user, project_feature_attributes: { wiki_access_level: ProjectFeature::ENABLED })
      end
    end

191
192
193
194
195
196
    context 'when updating a project that contains container images' do
      before do
        stub_container_registry_config(enabled: true)
        stub_container_registry_tags(repository: /image/, tags: %w[rc1])
        create(:container_repository, project: project, name: :image)
      end
197

198
199
      it 'does not allow to rename the project' do
        result = update_project(project, admin, path: 'renamed')
200

201
202
203
        expect(result).to include(status: :error)
        expect(result[:message]).to match(/contains container registry tags/)
      end
204

205
206
      it 'allows to update other settings' do
        result = update_project(project, admin, public_builds: true)
207

208
209
210
        expect(result[:status]).to eq :success
        expect(project.reload.public_builds).to be true
      end
211
    end
212

213
214
    context 'when renaming a project' do
      let(:repository_storage) { 'default' }
215
      let(:repository_storage_path) { Gitlab.config.repositories.storages[repository_storage].legacy_disk_path }
216

217
      context 'with legacy storage' do
Nick Thomas's avatar
Nick Thomas committed
218
219
        let(:project) { create(:project, :legacy_storage, :repository, creator: user, namespace: user.namespace) }

220
        before do
221
          gitlab_shell.create_repository(repository_storage, "#{user.namespace.full_path}/existing")
222
223
224
        end

        after do
225
          gitlab_shell.remove_repository(repository_storage, "#{user.namespace.full_path}/existing")
226
227
228
229
        end

        it 'does not allow renaming when new path matches existing repository on disk' do
          result = update_project(project, admin, path: 'existing')
230

231
232
233
234
235
236
          expect(result).to include(status: :error)
          expect(result[:message]).to match('There is already a repository with that name on disk')
          expect(project).not_to be_valid
          expect(project.errors.messages).to have_key(:base)
          expect(project.errors.messages[:base]).to include('There is already a repository with that name on disk')
        end
237
238
      end

239
240
      context 'with hashed storage' do
        let(:project) { create(:project, :repository, creator: user, namespace: user.namespace) }
241

242
243
244
245
246
247
248
249
250
251
252
        before do
          stub_application_setting(hashed_storage_enabled: true)
        end

        it 'does not check if new path matches existing repository on disk' do
          expect(project).not_to receive(:repository_with_same_path_already_exists?)

          result = update_project(project, admin, path: 'existing')

          expect(result).to include(status: :success)
        end
253
      end
254
255
    end

256
257
258
    context 'when passing invalid parameters' do
      it 'returns an error result when record cannot be updated' do
        result = update_project(project, admin, { name: 'foo&bar' })
259

260
261
262
263
        expect(result).to eq({
          status: :error,
          message: "Name can contain only letters, digits, emojis, '_', '.', dash, space. It must start with letter, digit, emoji or '_'."
        })
264
      end
265
    end
Rob Watson's avatar
Rob Watson committed
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286

    context 'when updating #pages_https_only', :https_pages_enabled do
      subject(:call_service) do
        update_project(project, admin, pages_https_only: false)
      end

      it 'updates the attribute' do
        expect { call_service }
          .to change { project.pages_https_only? }
          .to(false)
      end

      it 'calls Projects::UpdatePagesConfigurationService' do
        expect(Projects::UpdatePagesConfigurationService)
          .to receive(:new)
          .with(project)
          .and_call_original

        call_service
      end
    end
287
  end
288

289
  describe '#run_auto_devops_pipeline?' do
290
    subject { described_class.new(project, user).run_auto_devops_pipeline? }
291

292
293
294
295
    context 'when master contains a .gitlab-ci.yml file' do
      before do
        allow(project.repository).to receive(:gitlab_ci_yml).and_return("script: ['test']")
      end
296

297
298
299
      it { is_expected.to eq(false) }
    end

300
301
302
303
    context 'when auto devops is nil' do
      it { is_expected.to eq(false) }
    end

304
305
306
307
    context 'when auto devops is explicitly enabled' do
      before do
        project.create_auto_devops!(enabled: true)
      end
308
309

      it { is_expected.to eq(true) }
310
311
    end

312
313
314
315
    context 'when auto devops is explicitly disabled' do
      before do
        project.create_auto_devops!(enabled: false)
      end
316

317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
      it { is_expected.to eq(false) }
    end

    context 'when auto devops is set to instance setting' do
      before do
        project.create_auto_devops!(enabled: nil)
        allow(project.auto_devops).to receive(:previous_changes).and_return('enabled' => true)
      end

      context 'when auto devops is enabled system-wide' do
        before do
          stub_application_setting(auto_devops_enabled: true)
        end

        it { is_expected.to eq(true) }
      end

      context 'when auto devops is disabled system-wide' do
        before do
          stub_application_setting(auto_devops_enabled: false)
        end

        it { is_expected.to eq(false) }
      end
341
    end
342
343
  end

344
  def update_project(project, user, opts)
345
    described_class.new(project, user, opts).execute
346
  end
347
end