Read about our upcoming Code of Conduct on this issue

create_service_spec.rb 7.81 KB
Newer Older
1
2
require 'spec_helper'

3
describe Projects::CreateService, '#execute' do
4
  let(:gitlab_shell) { Gitlab::Shell.new }
Semyon Pupkov's avatar
Semyon Pupkov committed
5
6
7
  let(:user) { create :user }
  let(:opts) do
    {
8
9
      name: 'GitLab',
      namespace_id: user.namespace.id
Semyon Pupkov's avatar
Semyon Pupkov committed
10
11
    }
  end
12

Semyon Pupkov's avatar
Semyon Pupkov committed
13
14
15
  it 'creates labels on Project creation if there are templates' do
    Label.create(title: "bug", template: true)
    project = create_project(user, opts)
Valery Sizov's avatar
Valery Sizov committed
16

Semyon Pupkov's avatar
Semyon Pupkov committed
17
18
    expect(project.labels).not_to be_empty
  end
Valery Sizov's avatar
Valery Sizov committed
19

Semyon Pupkov's avatar
Semyon Pupkov committed
20
21
22
  context 'user namespace' do
    it do
      project = create_project(user, opts)
23

Semyon Pupkov's avatar
Semyon Pupkov committed
24
25
26
27
      expect(project).to be_valid
      expect(project.owner).to eq(user)
      expect(project.team.masters).to include(user)
      expect(project.namespace).to eq(user.namespace)
28
    end
Semyon Pupkov's avatar
Semyon Pupkov committed
29
  end
30

31
32
33
34
35
36
37
38
39
40
41
  context "admin creates project with other user's namespace_id" do
    it 'sets the correct permissions' do
      admin = create(:admin)
      opts = {
        name: 'GitLab',
        namespace_id: user.namespace.id
      }
      project = create_project(admin, opts)

      expect(project).to be_persisted
      expect(project.owner).to eq(user)
42
      expect(project.team.masters).to contain_exactly(user)
43
44
45
46
      expect(project.namespace).to eq(user.namespace)
    end
  end

Semyon Pupkov's avatar
Semyon Pupkov committed
47
48
49
50
51
52
  context 'group namespace' do
    let(:group) do
      create(:group).tap do |group|
        group.add_owner(user)
      end
    end
53

Semyon Pupkov's avatar
Semyon Pupkov committed
54
55
56
    before do
      user.refresh_authorized_projects # Ensure cache is warm
    end
57

Semyon Pupkov's avatar
Semyon Pupkov committed
58
59
    it do
      project = create_project(user, opts.merge!(namespace_id: group.id))
60

Semyon Pupkov's avatar
Semyon Pupkov committed
61
62
63
64
      expect(project).to be_valid
      expect(project.owner).to eq(group)
      expect(project.namespace).to eq(group)
      expect(user.authorized_projects).to include(project)
65
    end
Semyon Pupkov's avatar
Semyon Pupkov committed
66
  end
67

Semyon Pupkov's avatar
Semyon Pupkov committed
68
69
  context 'error handling' do
    it 'handles invalid options' do
Douwe Maan's avatar
Douwe Maan committed
70
      opts[:default_branch] = 'master'
Semyon Pupkov's avatar
Semyon Pupkov committed
71
      expect(create_project(user, opts)).to eq(nil)
72
    end
Semyon Pupkov's avatar
Semyon Pupkov committed
73
  end
74

Semyon Pupkov's avatar
Semyon Pupkov committed
75
76
77
78
79
  context 'wiki_enabled creates repository directory' do
    context 'wiki_enabled true creates wiki repository directory' do
      it do
        project = create_project(user, opts)
        path = ProjectWiki.new(project, user).send(:path_to_repo)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
80

Semyon Pupkov's avatar
Semyon Pupkov committed
81
        expect(File.exist?(path)).to be_truthy
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
82
      end
Semyon Pupkov's avatar
Semyon Pupkov committed
83
    end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
84

Semyon Pupkov's avatar
Semyon Pupkov committed
85
86
    context 'wiki_enabled false does not create wiki repository directory' do
      it do
Douwe Maan's avatar
Douwe Maan committed
87
        opts[:wiki_enabled] = false
Semyon Pupkov's avatar
Semyon Pupkov committed
88
89
        project = create_project(user, opts)
        path = ProjectWiki.new(project, user).send(:path_to_repo)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
90

Semyon Pupkov's avatar
Semyon Pupkov committed
91
        expect(File.exist?(path)).to be_falsey
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
92
93
      end
    end
Semyon Pupkov's avatar
Semyon Pupkov committed
94
  end
95

Semyon Pupkov's avatar
Semyon Pupkov committed
96
97
  context 'builds_enabled global setting' do
    let(:project) { create_project(user, opts) }
98

Semyon Pupkov's avatar
Semyon Pupkov committed
99
    subject { project.builds_enabled? }
100

Semyon Pupkov's avatar
Semyon Pupkov committed
101
102
103
    context 'global builds_enabled false does not enable CI by default' do
      before do
        project.project_feature.update_attribute(:builds_access_level, ProjectFeature::DISABLED)
104
105
      end

Semyon Pupkov's avatar
Semyon Pupkov committed
106
107
      it { is_expected.to be_falsey }
    end
108

Semyon Pupkov's avatar
Semyon Pupkov committed
109
110
    context 'global builds_enabled true does enable CI by default' do
      it { is_expected.to be_truthy }
111
    end
Semyon Pupkov's avatar
Semyon Pupkov committed
112
  end
113

Semyon Pupkov's avatar
Semyon Pupkov committed
114
115
116
  context 'restricted visibility level' do
    before do
      stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
117

Semyon Pupkov's avatar
Semyon Pupkov committed
118
      opts.merge!(
119
        visibility_level: Gitlab::VisibilityLevel::PUBLIC
Semyon Pupkov's avatar
Semyon Pupkov committed
120
121
      )
    end
122

Semyon Pupkov's avatar
Semyon Pupkov committed
123
124
125
126
127
128
129
130
    it 'does not allow a restricted visibility level for non-admins' do
      project = create_project(user, opts)
      expect(project).to respond_to(:errors)
      expect(project.errors.messages).to have_key(:visibility_level)
      expect(project.errors.messages[:visibility_level].first).to(
        match('restricted by your GitLab administrator')
      )
    end
131

Semyon Pupkov's avatar
Semyon Pupkov committed
132
133
134
    it 'allows a restricted visibility level for admins' do
      admin = create(:admin)
      project = create_project(admin, opts)
135

Semyon Pupkov's avatar
Semyon Pupkov committed
136
137
      expect(project.errors.any?).to be(false)
      expect(project.saved?).to be(true)
138
    end
Semyon Pupkov's avatar
Semyon Pupkov committed
139
  end
140

Semyon Pupkov's avatar
Semyon Pupkov committed
141
142
143
  context 'repository creation' do
    it 'synchronously creates the repository' do
      expect_any_instance_of(Project).to receive(:create_repository)
144

Semyon Pupkov's avatar
Semyon Pupkov committed
145
146
147
148
      project = create_project(user, opts)
      expect(project).to be_valid
      expect(project.owner).to eq(user)
      expect(project.namespace).to eq(user.namespace)
149
    end
150
151

    context 'when another repository already exists on disk' do
152
153
154
      let(:repository_storage) { 'default' }
      let(:repository_storage_path) { Gitlab.config.repositories.storages[repository_storage]['path'] }

155
156
157
158
159
160
161
      let(:opts) do
        {
          name: 'Existing',
          namespace_id: user.namespace.id
        }
      end

162
163
164
165
      context 'with legacy storage' do
        before do
          gitlab_shell.add_repository(repository_storage_path, "#{user.namespace.full_path}/existing")
        end
166

167
168
169
        after do
          gitlab_shell.remove_repository(repository_storage_path, "#{user.namespace.full_path}/existing")
        end
170

171
172
        it 'does not allow to create a project when path matches existing repository on disk' do
          project = create_project(user, opts)
173

174
175
176
177
178
          expect(project).not_to be_persisted
          expect(project).to respond_to(:errors)
          expect(project.errors.messages).to have_key(:base)
          expect(project.errors.messages[:base].first).to match('There is already a repository with that name on disk')
        end
179

180
181
182
183
184
185
186
187
        it 'does not allow to import project when path matches existing repository on disk' do
          project = create_project(user, opts.merge({ import_url: 'https://gitlab.com/gitlab-org/gitlab-test.git' }))

          expect(project).not_to be_persisted
          expect(project).to respond_to(:errors)
          expect(project.errors.messages).to have_key(:base)
          expect(project.errors.messages[:base].first).to match('There is already a repository with that name on disk')
        end
188
189
      end

190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
      context 'with hashed storage' do
        let(:hash) { '6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b' }
        let(:hashed_path) { '@hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b' }

        before do
          stub_application_setting(hashed_storage_enabled: true)
          allow(Digest::SHA2).to receive(:hexdigest) { hash }
        end

        before do
          gitlab_shell.add_repository(repository_storage_path, hashed_path)
        end

        after do
          gitlab_shell.remove_repository(repository_storage_path, hashed_path)
        end

        it 'does not allow to create a project when path matches existing repository on disk' do
          project = create_project(user, opts)
209

210
211
212
213
214
          expect(project).not_to be_persisted
          expect(project).to respond_to(:errors)
          expect(project.errors.messages).to have_key(:base)
          expect(project.errors.messages[:base].first).to match('There is already a repository with that name on disk')
        end
215
216
      end
    end
Semyon Pupkov's avatar
Semyon Pupkov committed
217
  end
218

Semyon Pupkov's avatar
Semyon Pupkov committed
219
220
221
222
  context 'when there is an active service template' do
    before do
      create(:service, project: nil, template: true, active: true)
    end
223

Semyon Pupkov's avatar
Semyon Pupkov committed
224
225
    it 'creates a service from this template' do
      project = create_project(user, opts)
226

Semyon Pupkov's avatar
Semyon Pupkov committed
227
      expect(project.services.count).to eq 1
228
    end
229
230
  end

231
232
233
  context 'when a bad service template is created' do
    it 'reports an error in the imported project' do
      opts[:import_url] = 'http://www.gitlab.com/gitlab-org/gitlab-ce'
234
235
      create(:service, type: 'DroneCiService', project: nil, template: true, active: true)

236
237
      project = create_project(user, opts)

238
      expect(project.errors.full_messages_for(:base).first).to match(/Unable to save project. Error: Unable to save DroneCiService/)
239
240
241
242
      expect(project.services.count).to eq 0
    end
  end

243
244
245
246
247
248
249
250
251
  context 'when skip_disk_validation is used' do
    it 'sets the project attribute' do
      opts[:skip_disk_validation] = true
      project = create_project(user, opts)

      expect(project.skip_disk_validation).to be_truthy
    end
  end

252
  def create_project(user, opts)
253
    Projects::CreateService.new(user, opts).execute
254
255
  end
end