Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorLuke "Jared" Bennett <lbennett@gitlab.com>2017-04-07 23:00:40 +0300
committerLuke "Jared" Bennett <lbennett@gitlab.com>2017-04-07 23:00:40 +0300
commit8b98ca50b3068fecc76233714fa7d363703ee55c (patch)
tree97d67331552de76faa9bfb8cec11616a369351fe /spec
parent501d403202d8b4f603dd1864790f56e85633b8ef (diff)
parentd37f1f1cd013a8b7a307e1004e020df086cba9d5 (diff)
Merge branch 'master' into new-resolvable-discussion
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects/builds_controller_spec.rb33
-rw-r--r--spec/controllers/projects/protected_branches_controller_spec.rb1
-rw-r--r--spec/controllers/projects/protected_tags_controller_spec.rb11
-rw-r--r--spec/factories/ci/trigger_schedules.rb4
-rw-r--r--spec/factories/protected_tags.rb22
-rw-r--r--spec/features/dashboard/projects_spec.rb11
-rw-r--r--spec/features/protected_branches/access_control_ce_spec.rb12
-rw-r--r--spec/features/protected_tags/access_control_ce_spec.rb46
-rw-r--r--spec/features/protected_tags_spec.rb94
-rw-r--r--spec/features/triggers_spec.rb53
-rw-r--r--spec/helpers/ci_status_helper_spec.rb6
-rw-r--r--spec/helpers/projects_helper_spec.rb2
-rw-r--r--spec/javascripts/merge_request_tabs_spec.js8
-rw-r--r--spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb (renamed from spec/models/ci/pipeline_status_spec.rb)33
-rw-r--r--spec/lib/gitlab/checks/change_access_spec.rb79
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml6
-rw-r--r--spec/lib/gitlab/import_export/project.json18
-rw-r--r--spec/lib/gitlab/import_export/project_tree_restorer_spec.rb4
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml16
-rw-r--r--spec/lib/gitlab/user_access_spec.rb69
-rw-r--r--spec/models/ci/pipeline_spec.rb15
-rw-r--r--spec/models/merge_request_spec.rb2
-rw-r--r--spec/models/project_spec.rb77
-rw-r--r--spec/models/protectable_dropdown_spec.rb25
-rw-r--r--spec/models/protected_branch_spec.rb64
-rw-r--r--spec/models/protected_tag_spec.rb12
-rw-r--r--spec/services/ci/expire_pipeline_cache_service_spec.rb7
-rw-r--r--spec/services/protected_branches/update_service_spec.rb26
-rw-r--r--spec/services/protected_tags/create_service_spec.rb21
-rw-r--r--spec/services/protected_tags/update_service_spec.rb26
-rw-r--r--spec/workers/trigger_schedule_worker_spec.rb33
31 files changed, 690 insertions, 146 deletions
diff --git a/spec/controllers/projects/builds_controller_spec.rb b/spec/controllers/projects/builds_controller_spec.rb
index 683667129e5..13208d21918 100644
--- a/spec/controllers/projects/builds_controller_spec.rb
+++ b/spec/controllers/projects/builds_controller_spec.rb
@@ -10,6 +10,39 @@ describe Projects::BuildsController do
sign_in(user)
end
+ describe 'GET index' do
+ context 'number of queries' do
+ before do
+ Ci::Build::AVAILABLE_STATUSES.each do |status|
+ create_build(status, status)
+ end
+
+ RequestStore.begin!
+ end
+
+ after do
+ RequestStore.end!
+ RequestStore.clear!
+ end
+
+ def render
+ get :index, namespace_id: project.namespace,
+ project_id: project
+ end
+
+ it "verifies number of queries" do
+ recorded = ActiveRecord::QueryRecorder.new { render }
+ expect(recorded.count).to be_within(5).of(8)
+ end
+
+ def create_build(name, status)
+ pipeline = create(:ci_pipeline, project: project)
+ create(:ci_build, :tags, :triggered, :artifacts,
+ pipeline: pipeline, name: name, status: status)
+ end
+ end
+ end
+
describe 'GET status.json' do
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:build) { create(:ci_build, pipeline: pipeline) }
diff --git a/spec/controllers/projects/protected_branches_controller_spec.rb b/spec/controllers/projects/protected_branches_controller_spec.rb
index e378b5714fe..80be135b5d8 100644
--- a/spec/controllers/projects/protected_branches_controller_spec.rb
+++ b/spec/controllers/projects/protected_branches_controller_spec.rb
@@ -3,6 +3,7 @@ require('spec_helper')
describe Projects::ProtectedBranchesController do
describe "GET #index" do
let(:project) { create(:project_empty_repo, :public) }
+
it "redirects empty repo to projects page" do
get(:index, namespace_id: project.namespace.to_param, project_id: project)
end
diff --git a/spec/controllers/projects/protected_tags_controller_spec.rb b/spec/controllers/projects/protected_tags_controller_spec.rb
new file mode 100644
index 00000000000..64658988b3f
--- /dev/null
+++ b/spec/controllers/projects/protected_tags_controller_spec.rb
@@ -0,0 +1,11 @@
+require('spec_helper')
+
+describe Projects::ProtectedTagsController do
+ describe "GET #index" do
+ let(:project) { create(:project_empty_repo, :public) }
+
+ it "redirects empty repo to projects page" do
+ get(:index, namespace_id: project.namespace.to_param, project_id: project)
+ end
+ end
+end
diff --git a/spec/factories/ci/trigger_schedules.rb b/spec/factories/ci/trigger_schedules.rb
index 315bce16995..2390706fa41 100644
--- a/spec/factories/ci/trigger_schedules.rb
+++ b/spec/factories/ci/trigger_schedules.rb
@@ -3,9 +3,11 @@ FactoryGirl.define do
trigger factory: :ci_trigger_for_trigger_schedule
cron '0 1 * * *'
cron_timezone Gitlab::Ci::CronParser::VALID_SYNTAX_SAMPLE_TIME_ZONE
+ ref 'master'
+ active true
after(:build) do |trigger_schedule, evaluator|
- trigger_schedule.update!(project: trigger_schedule.trigger.project)
+ trigger_schedule.project ||= trigger_schedule.trigger.project
end
trait :nightly do
diff --git a/spec/factories/protected_tags.rb b/spec/factories/protected_tags.rb
new file mode 100644
index 00000000000..d8e90ae1ee1
--- /dev/null
+++ b/spec/factories/protected_tags.rb
@@ -0,0 +1,22 @@
+FactoryGirl.define do
+ factory :protected_tag do
+ name
+ project
+
+ after(:build) do |protected_tag|
+ protected_tag.create_access_levels.new(access_level: Gitlab::Access::MASTER)
+ end
+
+ trait :developers_can_create do
+ after(:create) do |protected_tag|
+ protected_tag.create_access_levels.first.update!(access_level: Gitlab::Access::DEVELOPER)
+ end
+ end
+
+ trait :no_one_can_create do
+ after(:create) do |protected_tag|
+ protected_tag.create_access_levels.first.update!(access_level: Gitlab::Access::NO_ACCESS)
+ end
+ end
+ end
+end
diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb
index c4e58d14f75..f1789fc9d43 100644
--- a/spec/features/dashboard/projects_spec.rb
+++ b/spec/features/dashboard/projects_spec.rb
@@ -7,7 +7,6 @@ RSpec.describe 'Dashboard Projects', feature: true do
before do
project.team << [user, :developer]
login_as user
- visit dashboard_projects_path
end
it 'shows the project the user in a member of in the list' do
@@ -15,15 +14,19 @@ RSpec.describe 'Dashboard Projects', feature: true do
expect(page).to have_content('awesome stuff')
end
- describe "with a pipeline" do
- let(:pipeline) { create(:ci_pipeline, :success, project: project, sha: project.commit.sha) }
+ describe "with a pipeline", redis: true do
+ let!(:pipeline) { create(:ci_pipeline, project: project, sha: project.commit.sha) }
before do
- pipeline
+ # Since the cache isn't updated when a new pipeline is created
+ # we need the pipeline to advance in the pipeline since the cache was created
+ # by visiting the login page.
+ pipeline.succeed
end
it 'shows that the last pipeline passed' do
visit dashboard_projects_path
+
expect(page).to have_xpath("//a[@href='#{pipelines_namespace_project_commit_path(project.namespace, project, project.commit)}']")
end
end
diff --git a/spec/features/protected_branches/access_control_ce_spec.rb b/spec/features/protected_branches/access_control_ce_spec.rb
index e4aca25a339..eb3cea775da 100644
--- a/spec/features/protected_branches/access_control_ce_spec.rb
+++ b/spec/features/protected_branches/access_control_ce_spec.rb
@@ -2,7 +2,9 @@ RSpec.shared_examples "protected branches > access control > CE" do
ProtectedBranch::PushAccessLevel.human_access_levels.each do |(access_type_id, access_type_name)|
it "allows creating protected branches that #{access_type_name} can push to" do
visit namespace_project_protected_branches_path(project.namespace, project)
+
set_protected_branch_name('master')
+
within('.new_protected_branch') do
allowed_to_push_button = find(".js-allowed-to-push")
@@ -11,6 +13,7 @@ RSpec.shared_examples "protected branches > access control > CE" do
within(".dropdown.open .dropdown-menu") { click_on access_type_name }
end
end
+
click_on "Protect"
expect(ProtectedBranch.count).to eq(1)
@@ -19,7 +22,9 @@ RSpec.shared_examples "protected branches > access control > CE" do
it "allows updating protected branches so that #{access_type_name} can push to them" do
visit namespace_project_protected_branches_path(project.namespace, project)
+
set_protected_branch_name('master')
+
click_on "Protect"
expect(ProtectedBranch.count).to eq(1)
@@ -34,6 +39,7 @@ RSpec.shared_examples "protected branches > access control > CE" do
end
wait_for_ajax
+
expect(ProtectedBranch.last.push_access_levels.map(&:access_level)).to include(access_type_id)
end
end
@@ -41,7 +47,9 @@ RSpec.shared_examples "protected branches > access control > CE" do
ProtectedBranch::MergeAccessLevel.human_access_levels.each do |(access_type_id, access_type_name)|
it "allows creating protected branches that #{access_type_name} can merge to" do
visit namespace_project_protected_branches_path(project.namespace, project)
+
set_protected_branch_name('master')
+
within('.new_protected_branch') do
allowed_to_merge_button = find(".js-allowed-to-merge")
@@ -50,6 +58,7 @@ RSpec.shared_examples "protected branches > access control > CE" do
within(".dropdown.open .dropdown-menu") { click_on access_type_name }
end
end
+
click_on "Protect"
expect(ProtectedBranch.count).to eq(1)
@@ -58,7 +67,9 @@ RSpec.shared_examples "protected branches > access control > CE" do
it "allows updating protected branches so that #{access_type_name} can merge to them" do
visit namespace_project_protected_branches_path(project.namespace, project)
+
set_protected_branch_name('master')
+
click_on "Protect"
expect(ProtectedBranch.count).to eq(1)
@@ -73,6 +84,7 @@ RSpec.shared_examples "protected branches > access control > CE" do
end
wait_for_ajax
+
expect(ProtectedBranch.last.merge_access_levels.map(&:access_level)).to include(access_type_id)
end
end
diff --git a/spec/features/protected_tags/access_control_ce_spec.rb b/spec/features/protected_tags/access_control_ce_spec.rb
new file mode 100644
index 00000000000..5b2baf8616c
--- /dev/null
+++ b/spec/features/protected_tags/access_control_ce_spec.rb
@@ -0,0 +1,46 @@
+RSpec.shared_examples "protected tags > access control > CE" do
+ ProtectedTag::CreateAccessLevel.human_access_levels.each do |(access_type_id, access_type_name)|
+ it "allows creating protected tags that #{access_type_name} can create" do
+ visit namespace_project_protected_tags_path(project.namespace, project)
+
+ set_protected_tag_name('master')
+
+ within('.js-new-protected-tag') do
+ allowed_to_create_button = find(".js-allowed-to-create")
+
+ unless allowed_to_create_button.text == access_type_name
+ allowed_to_create_button.click
+ within(".dropdown.open .dropdown-menu") { click_on access_type_name }
+ end
+ end
+
+ click_on "Protect"
+
+ expect(ProtectedTag.count).to eq(1)
+ expect(ProtectedTag.last.create_access_levels.map(&:access_level)).to eq([access_type_id])
+ end
+
+ it "allows updating protected tags so that #{access_type_name} can create them" do
+ visit namespace_project_protected_tags_path(project.namespace, project)
+
+ set_protected_tag_name('master')
+
+ click_on "Protect"
+
+ expect(ProtectedTag.count).to eq(1)
+
+ within(".protected-tags-list") do
+ find(".js-allowed-to-create").click
+
+ within('.js-allowed-to-create-container') do
+ expect(first("li")).to have_content("Roles")
+ click_on access_type_name
+ end
+ end
+
+ wait_for_ajax
+
+ expect(ProtectedTag.last.create_access_levels.map(&:access_level)).to include(access_type_id)
+ end
+ end
+end
diff --git a/spec/features/protected_tags_spec.rb b/spec/features/protected_tags_spec.rb
new file mode 100644
index 00000000000..09e8c850de3
--- /dev/null
+++ b/spec/features/protected_tags_spec.rb
@@ -0,0 +1,94 @@
+require 'spec_helper'
+Dir["./spec/features/protected_tags/*.rb"].sort.each { |f| require f }
+
+feature 'Projected Tags', feature: true, js: true do
+ include WaitForAjax
+
+ let(:user) { create(:user, :admin) }
+ let(:project) { create(:project) }
+
+ before { login_as(user) }
+
+ def set_protected_tag_name(tag_name)
+ find(".js-protected-tag-select").click
+ find(".dropdown-input-field").set(tag_name)
+ click_on("Create wildcard #{tag_name}")
+ end
+
+ describe "explicit protected tags" do
+ it "allows creating explicit protected tags" do
+ visit namespace_project_protected_tags_path(project.namespace, project)
+ set_protected_tag_name('some-tag')
+ click_on "Protect"
+
+ within(".protected-tags-list") { expect(page).to have_content('some-tag') }
+ expect(ProtectedTag.count).to eq(1)
+ expect(ProtectedTag.last.name).to eq('some-tag')
+ end
+
+ it "displays the last commit on the matching tag if it exists" do
+ commit = create(:commit, project: project)
+ project.repository.add_tag(user, 'some-tag', commit.id)
+
+ visit namespace_project_protected_tags_path(project.namespace, project)
+ set_protected_tag_name('some-tag')
+ click_on "Protect"
+
+ within(".protected-tags-list") { expect(page).to have_content(commit.id[0..7]) }
+ end
+
+ it "displays an error message if the named tag does not exist" do
+ visit namespace_project_protected_tags_path(project.namespace, project)
+ set_protected_tag_name('some-tag')
+ click_on "Protect"
+
+ within(".protected-tags-list") { expect(page).to have_content('tag was removed') }
+ end
+ end
+
+ describe "wildcard protected tags" do
+ it "allows creating protected tags with a wildcard" do
+ visit namespace_project_protected_tags_path(project.namespace, project)
+ set_protected_tag_name('*-stable')
+ click_on "Protect"
+
+ within(".protected-tags-list") { expect(page).to have_content('*-stable') }
+ expect(ProtectedTag.count).to eq(1)
+ expect(ProtectedTag.last.name).to eq('*-stable')
+ end
+
+ it "displays the number of matching tags" do
+ project.repository.add_tag(user, 'production-stable', 'master')
+ project.repository.add_tag(user, 'staging-stable', 'master')
+
+ visit namespace_project_protected_tags_path(project.namespace, project)
+ set_protected_tag_name('*-stable')
+ click_on "Protect"
+
+ within(".protected-tags-list") { expect(page).to have_content("2 matching tags") }
+ end
+
+ it "displays all the tags matching the wildcard" do
+ project.repository.add_tag(user, 'production-stable', 'master')
+ project.repository.add_tag(user, 'staging-stable', 'master')
+ project.repository.add_tag(user, 'development', 'master')
+
+ visit namespace_project_protected_tags_path(project.namespace, project)
+ set_protected_tag_name('*-stable')
+ click_on "Protect"
+
+ visit namespace_project_protected_tags_path(project.namespace, project)
+ click_on "2 matching tags"
+
+ within(".protected-tags-list") do
+ expect(page).to have_content("production-stable")
+ expect(page).to have_content("staging-stable")
+ expect(page).not_to have_content("development")
+ end
+ end
+ end
+
+ describe "access control" do
+ include_examples "protected tags > access control > CE"
+ end
+end
diff --git a/spec/features/triggers_spec.rb b/spec/features/triggers_spec.rb
index c1ae6db00c6..81fa2de1cc3 100644
--- a/spec/features/triggers_spec.rb
+++ b/spec/features/triggers_spec.rb
@@ -77,6 +77,59 @@ feature 'Triggers', feature: true, js: true do
expect(page.find('.flash-notice')).to have_content 'Trigger was successfully updated.'
expect(page.find('.triggers-list')).to have_content new_trigger_title
end
+
+ context 'scheduled triggers' do
+ let!(:trigger) do
+ create(:ci_trigger, owner: user, project: @project, description: trigger_title)
+ end
+
+ context 'enabling schedule' do
+ before do
+ visit edit_namespace_project_trigger_path(@project.namespace, @project, trigger)
+ end
+
+ scenario 'do fill form with valid data and save' do
+ find('#trigger_trigger_schedule_attributes_active').click
+ fill_in 'trigger_trigger_schedule_attributes_cron', with: '1 * * * *'
+ fill_in 'trigger_trigger_schedule_attributes_cron_timezone', with: 'UTC'
+ fill_in 'trigger_trigger_schedule_attributes_ref', with: 'master'
+ click_button 'Save trigger'
+
+ expect(page.find('.flash-notice')).to have_content 'Trigger was successfully updated.'
+ end
+
+ scenario 'do not fill form with valid data and save' do
+ find('#trigger_trigger_schedule_attributes_active').click
+ click_button 'Save trigger'
+
+ expect(page).to have_content 'The form contains the following errors'
+ end
+ end
+
+ context 'disabling schedule' do
+ before do
+ trigger.create_trigger_schedule(
+ project: trigger.project,
+ active: true,
+ ref: 'master',
+ cron: '1 * * * *',
+ cron_timezone: 'UTC')
+
+ visit edit_namespace_project_trigger_path(@project.namespace, @project, trigger)
+ end
+
+ scenario 'disable and save form' do
+ find('#trigger_trigger_schedule_attributes_active').click
+ click_button 'Save trigger'
+ expect(page.find('.flash-notice')).to have_content 'Trigger was successfully updated.'
+
+ visit edit_namespace_project_trigger_path(@project.namespace, @project, trigger)
+ checkbox = find_field('trigger_trigger_schedule_attributes_active')
+
+ expect(checkbox).not_to be_checked
+ end
+ end
+ end
end
describe 'trigger "Take ownership" workflow' do
diff --git a/spec/helpers/ci_status_helper_spec.rb b/spec/helpers/ci_status_helper_spec.rb
index 174cc84a97b..c795fe5a2a3 100644
--- a/spec/helpers/ci_status_helper_spec.rb
+++ b/spec/helpers/ci_status_helper_spec.rb
@@ -19,7 +19,11 @@ describe CiStatusHelper do
describe "#pipeline_status_cache_key" do
it "builds a cache key for pipeline status" do
- pipeline_status = Ci::PipelineStatus.new(build(:project), sha: "123abc", status: "success")
+ pipeline_status = Gitlab::Cache::Ci::ProjectPipelineStatus.new(
+ build(:project),
+ sha: "123abc",
+ status: "success"
+ )
expect(helper.pipeline_status_cache_key(pipeline_status)).to eq("pipeline-status/123abc-success")
end
end
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index 44312ada438..40efab6e4f7 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -63,7 +63,7 @@ describe ProjectsHelper do
end
end
- describe "#project_list_cache_key" do
+ describe "#project_list_cache_key", redis: true do
let(:project) { create(:project) }
it "includes the namespace" do
diff --git a/spec/javascripts/merge_request_tabs_spec.js b/spec/javascripts/merge_request_tabs_spec.js
index 5354e536edc..e437333d522 100644
--- a/spec/javascripts/merge_request_tabs_spec.js
+++ b/spec/javascripts/merge_request_tabs_spec.js
@@ -1,6 +1,7 @@
/* eslint-disable no-var, comma-dangle, object-shorthand */
require('~/merge_request_tabs');
+require('~/commit/pipelines/pipelines_bundle.js');
require('~/breakpoints');
require('~/lib/utils/common_utils');
require('~/diff');
@@ -222,7 +223,9 @@ require('vendor/jquery.scrollTo');
describe('#tabShown', () => {
beforeEach(function () {
- spyOn($, 'ajax').and.callFake(function () {});
+ spyOn($, 'ajax').and.callFake(function (options) {
+ options.success({ html: '' });
+ });
loadFixtures('merge_requests/merge_request_with_task_list.html.raw');
});
@@ -230,9 +233,6 @@ require('vendor/jquery.scrollTo');
beforeEach(function () {
this.class.diffViewType = () => 'parallel';
gl.Diff.prototype.diffViewType = () => 'parallel';
- spyOn($, 'ajax').and.callFake(function (options) {
- options.success({ html: '' });
- });
});
it('maintains `container-limited` for pipelines tab', function (done) {
diff --git a/spec/models/ci/pipeline_status_spec.rb b/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb
index bc5b71666c2..fced253dd01 100644
--- a/spec/models/ci/pipeline_status_spec.rb
+++ b/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe Ci::PipelineStatus do
+describe Gitlab::Cache::Ci::ProjectPipelineStatus do
let(:project) { create(:project) }
let(:pipeline_status) { described_class.new(project) }
@@ -12,6 +12,20 @@ describe Ci::PipelineStatus do
end
end
+ describe '.update_for_pipeline' do
+ it 'refreshes the cache if nescessary' do
+ pipeline = build_stubbed(:ci_pipeline, sha: '123456', status: 'success')
+ fake_status = double
+ expect(described_class).to receive(:new).
+ with(pipeline.project, sha: '123456', status: 'success', ref: 'master').
+ and_return(fake_status)
+
+ expect(fake_status).to receive(:store_in_cache_if_needed)
+
+ described_class.update_for_pipeline(pipeline)
+ end
+ end
+
describe '#has_status?' do
it "is false when the status wasn't loaded yet" do
expect(pipeline_status.has_status?).to be_falsy
@@ -41,14 +55,14 @@ describe Ci::PipelineStatus do
it 'loads the status from the project commit when there is no cache' do
allow(pipeline_status).to receive(:has_cache?).and_return(false)
- expect(pipeline_status).to receive(:load_from_commit)
+ expect(pipeline_status).to receive(:load_from_project)
pipeline_status.load_status
end
it 'stores the status in the cache when it loading it from the project' do
allow(pipeline_status).to receive(:has_cache?).and_return(false)
- allow(pipeline_status).to receive(:load_from_commit)
+ allow(pipeline_status).to receive(:load_from_project)
expect(pipeline_status).to receive(:store_in_cache)
@@ -70,14 +84,15 @@ describe Ci::PipelineStatus do
end
end
- describe "#load_from_commit" do
+ describe "#load_from_project" do
let!(:pipeline) { create(:ci_pipeline, :success, project: project, sha: project.commit.sha) }
it 'reads the status from the pipeline for the commit' do
- pipeline_status.load_from_commit
+ pipeline_status.load_from_project
expect(pipeline_status.status).to eq('success')
expect(pipeline_status.sha).to eq(project.commit.sha)
+ expect(pipeline_status.ref).to eq(project.default_branch)
end
it "doesn't fail for an empty project" do
@@ -108,10 +123,11 @@ describe Ci::PipelineStatus do
build_status = described_class.load_for_project(project)
build_status.store_in_cache_if_needed
- sha, status = Gitlab::Redis.with { |redis| redis.hmget("projects/#{project.id}/build_status", :sha, :status) }
+ sha, status, ref = Gitlab::Redis.with { |redis| redis.hmget("projects/#{project.id}/build_status", :sha, :status, :ref) }
expect(sha).not_to be_nil
expect(status).not_to be_nil
+ expect(ref).not_to be_nil
end
it "doesn't store the status in redis when the sha is not the head of the project" do
@@ -126,14 +142,15 @@ describe Ci::PipelineStatus do
it "deletes the cache if the repository doesn't have a head commit" do
empty_project = create(:empty_project)
- Gitlab::Redis.with { |redis| redis.mapped_hmset("projects/#{empty_project.id}/build_status", { sha: "sha", status: "pending" }) }
+ Gitlab::Redis.with { |redis| redis.mapped_hmset("projects/#{empty_project.id}/build_status", { sha: "sha", status: "pending", ref: 'master' }) }
other_status = described_class.new(empty_project, sha: "123456", status: "failed")
other_status.store_in_cache_if_needed
- sha, status = Gitlab::Redis.with { |redis| redis.hmget("projects/#{empty_project.id}/build_status", :sha, :status) }
+ sha, status, ref = Gitlab::Redis.with { |redis| redis.hmget("projects/#{empty_project.id}/build_status", :sha, :status, :ref) }
expect(sha).to be_nil
expect(status).to be_nil
+ expect(ref).to be_nil
end
end
diff --git a/spec/lib/gitlab/checks/change_access_spec.rb b/spec/lib/gitlab/checks/change_access_spec.rb
index e22f88b7a32..959ae02c222 100644
--- a/spec/lib/gitlab/checks/change_access_spec.rb
+++ b/spec/lib/gitlab/checks/change_access_spec.rb
@@ -5,13 +5,10 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
let(:user) { create(:user) }
let(:project) { create(:project, :repository) }
let(:user_access) { Gitlab::UserAccess.new(user, project: project) }
- let(:changes) do
- {
- oldrev: 'be93687618e4b132087f430a4d8fc3a609c9b77c',
- newrev: '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51',
- ref: 'refs/heads/master'
- }
- end
+ let(:oldrev) { 'be93687618e4b132087f430a4d8fc3a609c9b77c' }
+ let(:newrev) { '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51' }
+ let(:ref) { 'refs/heads/master' }
+ let(:changes) { { oldrev: oldrev, newrev: newrev, ref: ref } }
let(:protocol) { 'ssh' }
subject do
@@ -23,7 +20,7 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
).exec
end
- before { allow(user_access).to receive(:can_do_action?).with(:push_code).and_return(true) }
+ before { project.add_developer(user) }
context 'without failed checks' do
it "doesn't return any error" do
@@ -41,25 +38,67 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
end
context 'tags check' do
- let(:changes) do
- {
- oldrev: 'be93687618e4b132087f430a4d8fc3a609c9b77c',
- newrev: '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51',
- ref: 'refs/tags/v1.0.0'
- }
- end
+ let(:ref) { 'refs/tags/v1.0.0' }
it 'returns an error if the user is not allowed to update tags' do
+ allow(user_access).to receive(:can_do_action?).with(:push_code).and_return(true)
expect(user_access).to receive(:can_do_action?).with(:admin_project).and_return(false)
expect(subject.status).to be(false)
expect(subject.message).to eq('You are not allowed to change existing tags on this project.')
end
+
+ context 'with protected tag' do
+ let!(:protected_tag) { create(:protected_tag, project: project, name: 'v*') }
+
+ context 'as master' do
+ before { project.add_master(user) }
+
+ context 'deletion' do
+ let(:oldrev) { 'be93687618e4b132087f430a4d8fc3a609c9b77c' }
+ let(:newrev) { '0000000000000000000000000000000000000000' }
+
+ it 'is prevented' do
+ expect(subject.status).to be(false)
+ expect(subject.message).to include('cannot be deleted')
+ end
+ end
+
+ context 'update' do
+ let(:oldrev) { 'be93687618e4b132087f430a4d8fc3a609c9b77c' }
+ let(:newrev) { '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51' }
+
+ it 'is prevented' do
+ expect(subject.status).to be(false)
+ expect(subject.message).to include('cannot be updated')
+ end
+ end
+ end
+
+ context 'creation' do
+ let(:oldrev) { '0000000000000000000000000000000000000000' }
+ let(:newrev) { '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51' }
+ let(:ref) { 'refs/tags/v9.1.0' }
+
+ it 'prevents creation below access level' do
+ expect(subject.status).to be(false)
+ expect(subject.message).to include('allowed to create this tag as it is protected')
+ end
+
+ context 'when user has access' do
+ let!(:protected_tag) { create(:protected_tag, :developers_can_create, project: project, name: 'v*') }
+
+ it 'allows tag creation' do
+ expect(subject.status).to be(true)
+ end
+ end
+ end
+ end
end
context 'protected branches check' do
before do
- allow(project).to receive(:protected_branch?).with('master').and_return(true)
+ allow(ProtectedBranch).to receive(:protected?).with(project, 'master').and_return(true)
end
it 'returns an error if the user is not allowed to do forced pushes to protected branches' do
@@ -86,13 +125,7 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
end
context 'branch deletion' do
- let(:changes) do
- {
- oldrev: 'be93687618e4b132087f430a4d8fc3a609c9b77c',
- newrev: '0000000000000000000000000000000000000000',
- ref: 'refs/heads/master'
- }
- end
+ let(:newrev) { '0000000000000000000000000000000000000000' }
it 'returns an error if the user is not allowed to delete protected branches' do
expect(subject.status).to be(false)
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 9770d2e3b13..0abf89d060c 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -124,10 +124,15 @@ protected_branches:
- project
- merge_access_levels
- push_access_levels
+protected_tags:
+- project
+- create_access_levels
merge_access_levels:
- protected_branch
push_access_levels:
- protected_branch
+create_access_levels:
+- protected_tag
container_repositories:
- project
- name
@@ -188,6 +193,7 @@ project:
- snippets
- hooks
- protected_branches
+- protected_tags
- project_members
- users
- requesters
diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json
index d9b67426818..7a0b0b06d4b 100644
--- a/spec/lib/gitlab/import_export/project.json
+++ b/spec/lib/gitlab/import_export/project.json
@@ -7455,6 +7455,24 @@
]
}
],
+ "protected_tags": [
+ {
+ "id": 1,
+ "project_id": 9,
+ "name": "v*",
+ "created_at": "2017-04-04T13:48:13.426Z",
+ "updated_at": "2017-04-04T13:48:13.426Z",
+ "create_access_levels": [
+ {
+ "id": 1,
+ "protected_tag_id": 1,
+ "access_level": 40,
+ "created_at": "2017-04-04T13:48:13.458Z",
+ "updated_at": "2017-04-04T13:48:13.458Z"
+ }
+ ]
+ }
+ ],
"project_feature": {
"builds_access_level": 0,
"created_at": "2014-12-26T09:26:45.000Z",
diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
index af9c25acb02..0e9607c5bd3 100644
--- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
@@ -64,6 +64,10 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do
expect(ProtectedBranch.first.push_access_levels).not_to be_empty
end
+ it 'contains the create access levels on a protected tag' do
+ expect(ProtectedTag.first.create_access_levels).not_to be_empty
+ end
+
context 'event at forth level of the tree' do
let(:event) { Event.where(title: 'test levels').first }
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index 04b5c80f22d..0372e3f7dbf 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -253,6 +253,8 @@ Ci::TriggerSchedule:
- cron
- cron_timezone
- next_run_at
+- ref
+- active
DeployKey:
- id
- user_id
@@ -313,6 +315,12 @@ ProtectedBranch:
- name
- created_at
- updated_at
+ProtectedTag:
+- id
+- project_id
+- name
+- created_at
+- updated_at
Project:
- description
- issues_enabled
@@ -346,6 +354,14 @@ ProtectedBranch::PushAccessLevel:
- access_level
- created_at
- updated_at
+ProtectedTag::CreateAccessLevel:
+- id
+- protected_tag_id
+- access_level
+- created_at
+- updated_at
+- user_id
+- group_id
AwardEmoji:
- id
- user_id
diff --git a/spec/lib/gitlab/user_access_spec.rb b/spec/lib/gitlab/user_access_spec.rb
index 369e55f61f1..611cdbbc865 100644
--- a/spec/lib/gitlab/user_access_spec.rb
+++ b/spec/lib/gitlab/user_access_spec.rb
@@ -142,4 +142,73 @@ describe Gitlab::UserAccess, lib: true do
end
end
end
+
+ describe 'can_create_tag?' do
+ describe 'push to none protected tag' do
+ it 'returns true if user is a master' do
+ project.add_user(user, :master)
+
+ expect(access.can_create_tag?('random_tag')).to be_truthy
+ end
+
+ it 'returns true if user is a developer' do
+ project.add_user(user, :developer)
+
+ expect(access.can_create_tag?('random_tag')).to be_truthy
+ end
+
+ it 'returns false if user is a reporter' do
+ project.add_user(user, :reporter)
+
+ expect(access.can_create_tag?('random_tag')).to be_falsey
+ end
+ end
+
+ describe 'push to protected tag' do
+ let(:tag) { create(:protected_tag, project: project, name: "test") }
+ let(:not_existing_tag) { create :protected_tag, project: project }
+
+ it 'returns true if user is a master' do
+ project.add_user(user, :master)
+
+ expect(access.can_create_tag?(tag.name)).to be_truthy
+ end
+
+ it 'returns false if user is a developer' do
+ project.add_user(user, :developer)
+
+ expect(access.can_create_tag?(tag.name)).to be_falsey
+ end
+
+ it 'returns false if user is a reporter' do
+ project.add_user(user, :reporter)
+
+ expect(access.can_create_tag?(tag.name)).to be_falsey
+ end
+ end
+
+ describe 'push to protected tag if allowed for developers' do
+ before do
+ @tag = create(:protected_tag, :developers_can_create, project: project)
+ end
+
+ it 'returns true if user is a master' do
+ project.add_user(user, :master)
+
+ expect(access.can_create_tag?(@tag.name)).to be_truthy
+ end
+
+ it 'returns true if user is a developer' do
+ project.add_user(user, :developer)
+
+ expect(access.can_create_tag?(@tag.name)).to be_truthy
+ end
+
+ it 'returns false if user is a reporter' do
+ project.add_user(user, :reporter)
+
+ expect(access.can_create_tag?(@tag.name)).to be_falsey
+ end
+ end
+ end
end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 32aa2f4b336..d7d6a75d38d 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -375,7 +375,7 @@ describe Ci::Pipeline, models: true do
end
end
- describe 'pipeline ETag caching' do
+ describe 'pipeline caching' do
it 'executes ExpirePipelinesCacheService' do
expect_any_instance_of(Ci::ExpirePipelineCacheService).to receive(:execute).with(pipeline)
@@ -1079,19 +1079,6 @@ describe Ci::Pipeline, models: true do
end
end
- describe '#update_status' do
- let(:pipeline) { create(:ci_pipeline, sha: '123456') }
-
- it 'updates the cached status' do
- fake_status = double
- # after updating the status, the status is set to `skipped` for this pipeline's builds
- expect(Ci::PipelineStatus).to receive(:new).with(pipeline.project, sha: '123456', status: 'skipped').and_return(fake_status)
- expect(fake_status).to receive(:store_in_cache_if_needed)
-
- pipeline.update_status
- end
- end
-
describe 'notifications when pipeline success or failed' do
let(:project) { create(:project, :repository) }
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index b615d956686..90b3a2ba42d 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -441,7 +441,7 @@ describe MergeRequest, models: true do
end
it "can't be removed when its a protected branch" do
- allow(subject.source_project).to receive(:protected_branch?).and_return(true)
+ allow(ProtectedBranch).to receive(:protected?).and_return(true)
expect(subject.can_remove_source_branch?(user)).to be_falsey
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 6d4ef78f8ec..92d420337f9 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -704,25 +704,6 @@ describe Project, models: true do
end
end
- describe '#open_branches' do
- let(:project) { create(:project, :repository) }
-
- before do
- project.protected_branches.create(name: 'master')
- end
-
- it { expect(project.open_branches.map(&:name)).to include('feature') }
- it { expect(project.open_branches.map(&:name)).not_to include('master') }
-
- it "includes branches matching a protected branch wildcard" do
- expect(project.open_branches.map(&:name)).to include('feature')
-
- create(:protected_branch, name: 'feat*', project: project)
-
- expect(Project.find(project.id).open_branches.map(&:name)).to include('feature')
- end
- end
-
describe '#star_count' do
it 'counts stars from multiple users' do
user1 = create :user
@@ -1297,62 +1278,6 @@ describe Project, models: true do
end
end
- describe '#protected_branch?' do
- context 'existing project' do
- let(:project) { create(:project, :repository) }
-
- it 'returns true when the branch matches a protected branch via direct match' do
- create(:protected_branch, project: project, name: "foo")
-
- expect(project.protected_branch?('foo')).to eq(true)
- end
-
- it 'returns true when the branch matches a protected branch via wildcard match' do
- create(:protected_branch, project: project, name: "production/*")
-
- expect(project.protected_branch?('production/some-branch')).to eq(true)
- end
-
- it 'returns false when the branch does not match a protected branch via direct match' do
- expect(project.protected_branch?('foo')).to eq(false)
- end
-
- it 'returns false when the branch does not match a protected branch via wildcard match' do
- create(:protected_branch, project: project, name: "production/*")
-
- expect(project.protected_branch?('staging/some-branch')).to eq(false)
- end
- end
-
- context "new project" do
- let(:project) { create(:empty_project) }
-
- it 'returns false when default_protected_branch is unprotected' do
- stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_NONE)
-
- expect(project.protected_branch?('master')).to be false
- end
-
- it 'returns false when default_protected_branch lets developers push' do
- stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_DEV_CAN_PUSH)
-
- expect(project.protected_branch?('master')).to be false
- end
-
- it 'returns true when default_branch_protection does not let developers push but let developer merge branches' do
- stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_DEV_CAN_MERGE)
-
- expect(project.protected_branch?('master')).to be true
- end
-
- it 'returns true when default_branch_protection is in full protection' do
- stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_FULL)
-
- expect(project.protected_branch?('master')).to be true
- end
- end
- end
-
describe '#user_can_push_to_empty_repo?' do
let(:project) { create(:empty_project) }
let(:user) { create(:user) }
@@ -1949,7 +1874,7 @@ describe Project, models: true do
describe '#pipeline_status' do
let(:project) { create(:project) }
it 'builds a pipeline status' do
- expect(project.pipeline_status).to be_a(Ci::PipelineStatus)
+ expect(project.pipeline_status).to be_a(Gitlab::Cache::Ci::ProjectPipelineStatus)
end
it 'hase a loaded pipeline status' do
diff --git a/spec/models/protectable_dropdown_spec.rb b/spec/models/protectable_dropdown_spec.rb
new file mode 100644
index 00000000000..4c9bade592b
--- /dev/null
+++ b/spec/models/protectable_dropdown_spec.rb
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe ProtectableDropdown, models: true do
+ let(:project) { create(:project, :repository) }
+ let(:subject) { described_class.new(project, :branches) }
+
+ describe '#protectable_ref_names' do
+ before do
+ project.protected_branches.create(name: 'master')
+ end
+
+ it { expect(subject.protectable_ref_names).to include('feature') }
+ it { expect(subject.protectable_ref_names).not_to include('master') }
+
+ it "includes branches matching a protected branch wildcard" do
+ expect(subject.protectable_ref_names).to include('feature')
+
+ create(:protected_branch, name: 'feat*', project: project)
+
+ subject = described_class.new(project.reload, :branches)
+
+ expect(subject.protectable_ref_names).to include('feature')
+ end
+ end
+end
diff --git a/spec/models/protected_branch_spec.rb b/spec/models/protected_branch_spec.rb
index 8bf0d24a128..179a443c43d 100644
--- a/spec/models/protected_branch_spec.rb
+++ b/spec/models/protected_branch_spec.rb
@@ -113,8 +113,8 @@ describe ProtectedBranch, models: true do
staging = build(:protected_branch, name: "staging")
expect(ProtectedBranch.matching("production")).to be_empty
- expect(ProtectedBranch.matching("production", protected_branches: [production, staging])).to include(production)
- expect(ProtectedBranch.matching("production", protected_branches: [production, staging])).not_to include(staging)
+ expect(ProtectedBranch.matching("production", protected_refs: [production, staging])).to include(production)
+ expect(ProtectedBranch.matching("production", protected_refs: [production, staging])).not_to include(staging)
end
end
@@ -132,8 +132,64 @@ describe ProtectedBranch, models: true do
staging = build(:protected_branch, name: "staging/*")
expect(ProtectedBranch.matching("production/some-branch")).to be_empty
- expect(ProtectedBranch.matching("production/some-branch", protected_branches: [production, staging])).to include(production)
- expect(ProtectedBranch.matching("production/some-branch", protected_branches: [production, staging])).not_to include(staging)
+ expect(ProtectedBranch.matching("production/some-branch", protected_refs: [production, staging])).to include(production)
+ expect(ProtectedBranch.matching("production/some-branch", protected_refs: [production, staging])).not_to include(staging)
+ end
+ end
+ end
+
+ describe '#protected?' do
+ context 'existing project' do
+ let(:project) { create(:project, :repository) }
+
+ it 'returns true when the branch matches a protected branch via direct match' do
+ create(:protected_branch, project: project, name: "foo")
+
+ expect(ProtectedBranch.protected?(project, 'foo')).to eq(true)
+ end
+
+ it 'returns true when the branch matches a protected branch via wildcard match' do
+ create(:protected_branch, project: project, name: "production/*")
+
+ expect(ProtectedBranch.protected?(project, 'production/some-branch')).to eq(true)
+ end
+
+ it 'returns false when the branch does not match a protected branch via direct match' do
+ expect(ProtectedBranch.protected?(project, 'foo')).to eq(false)
+ end
+
+ it 'returns false when the branch does not match a protected branch via wildcard match' do
+ create(:protected_branch, project: project, name: "production/*")
+
+ expect(ProtectedBranch.protected?(project, 'staging/some-branch')).to eq(false)
+ end
+ end
+
+ context "new project" do
+ let(:project) { create(:empty_project) }
+
+ it 'returns false when default_protected_branch is unprotected' do
+ stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_NONE)
+
+ expect(ProtectedBranch.protected?(project, 'master')).to be false
+ end
+
+ it 'returns false when default_protected_branch lets developers push' do
+ stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_DEV_CAN_PUSH)
+
+ expect(ProtectedBranch.protected?(project, 'master')).to be false
+ end
+
+ it 'returns true when default_branch_protection does not let developers push but let developer merge branches' do
+ stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_DEV_CAN_MERGE)
+
+ expect(ProtectedBranch.protected?(project, 'master')).to be true
+ end
+
+ it 'returns true when default_branch_protection is in full protection' do
+ stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_FULL)
+
+ expect(ProtectedBranch.protected?(project, 'master')).to be true
end
end
end
diff --git a/spec/models/protected_tag_spec.rb b/spec/models/protected_tag_spec.rb
new file mode 100644
index 00000000000..51353852a93
--- /dev/null
+++ b/spec/models/protected_tag_spec.rb
@@ -0,0 +1,12 @@
+require 'spec_helper'
+
+describe ProtectedTag, models: true do
+ describe 'Associations' do
+ it { is_expected.to belong_to(:project) }
+ end
+
+ describe 'Validation' do
+ it { is_expected.to validate_presence_of(:project) }
+ it { is_expected.to validate_presence_of(:name) }
+ end
+end
diff --git a/spec/services/ci/expire_pipeline_cache_service_spec.rb b/spec/services/ci/expire_pipeline_cache_service_spec.rb
index 3c735872c30..166c6dfc93e 100644
--- a/spec/services/ci/expire_pipeline_cache_service_spec.rb
+++ b/spec/services/ci/expire_pipeline_cache_service_spec.rb
@@ -16,5 +16,12 @@ describe Ci::ExpirePipelineCacheService, services: true do
subject.execute(pipeline)
end
+
+ it 'updates the cached status for a project' do
+ expect(Gitlab::Cache::Ci::ProjectPipelineStatus).to receive(:update_for_pipeline).
+ with(pipeline)
+
+ subject.execute(pipeline)
+ end
end
end
diff --git a/spec/services/protected_branches/update_service_spec.rb b/spec/services/protected_branches/update_service_spec.rb
new file mode 100644
index 00000000000..62bdd49a4d7
--- /dev/null
+++ b/spec/services/protected_branches/update_service_spec.rb
@@ -0,0 +1,26 @@
+require 'spec_helper'
+
+describe ProtectedBranches::UpdateService, services: true do
+ let(:protected_branch) { create(:protected_branch) }
+ let(:project) { protected_branch.project }
+ let(:user) { project.owner }
+ let(:params) { { name: 'new protected branch name' } }
+
+ describe '#execute' do
+ subject(:service) { described_class.new(project, user, params) }
+
+ it 'updates a protected branch' do
+ result = service.execute(protected_branch)
+
+ expect(result.reload.name).to eq(params[:name])
+ end
+
+ context 'without admin_project permissions' do
+ let(:user) { create(:user) }
+
+ it "raises error" do
+ expect{ service.execute(protected_branch) }.to raise_error(Gitlab::Access::AccessDeniedError)
+ end
+ end
+ end
+end
diff --git a/spec/services/protected_tags/create_service_spec.rb b/spec/services/protected_tags/create_service_spec.rb
new file mode 100644
index 00000000000..d91a58e8de5
--- /dev/null
+++ b/spec/services/protected_tags/create_service_spec.rb
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe ProtectedTags::CreateService, services: true do
+ let(:project) { create(:empty_project) }
+ let(:user) { project.owner }
+ let(:params) do
+ {
+ name: 'master',
+ create_access_levels_attributes: [{ access_level: Gitlab::Access::MASTER }]
+ }
+ end
+
+ describe '#execute' do
+ subject(:service) { described_class.new(project, user, params) }
+
+ it 'creates a new protected tag' do
+ expect { service.execute }.to change(ProtectedTag, :count).by(1)
+ expect(project.protected_tags.last.create_access_levels.map(&:access_level)).to eq([Gitlab::Access::MASTER])
+ end
+ end
+end
diff --git a/spec/services/protected_tags/update_service_spec.rb b/spec/services/protected_tags/update_service_spec.rb
new file mode 100644
index 00000000000..e78fde4c48d
--- /dev/null
+++ b/spec/services/protected_tags/update_service_spec.rb
@@ -0,0 +1,26 @@
+require 'spec_helper'
+
+describe ProtectedTags::UpdateService, services: true do
+ let(:protected_tag) { create(:protected_tag) }
+ let(:project) { protected_tag.project }
+ let(:user) { project.owner }
+ let(:params) { { name: 'new protected tag name' } }
+
+ describe '#execute' do
+ subject(:service) { described_class.new(project, user, params) }
+
+ it 'updates a protected tag' do
+ result = service.execute(protected_tag)
+
+ expect(result.reload.name).to eq(params[:name])
+ end
+
+ context 'without admin_project permissions' do
+ let(:user) { create(:user) }
+
+ it "raises error" do
+ expect{ service.execute(protected_tag) }.to raise_error(Gitlab::Access::AccessDeniedError)
+ end
+ end
+ end
+end
diff --git a/spec/workers/trigger_schedule_worker_spec.rb b/spec/workers/trigger_schedule_worker_spec.rb
index 151e1c2f7b9..861bed4442e 100644
--- a/spec/workers/trigger_schedule_worker_spec.rb
+++ b/spec/workers/trigger_schedule_worker_spec.rb
@@ -8,24 +8,39 @@ describe TriggerScheduleWorker do
end
context 'when there is a scheduled trigger within next_run_at' do
+ let(:next_run_at) { 2.days.ago }
+
+ let!(:trigger_schedule) do
+ create(:ci_trigger_schedule, :nightly)
+ end
+
before do
- trigger_schedule = create(:ci_trigger_schedule, :nightly)
- time_future = Time.now + 10.days
- allow(Time).to receive(:now).and_return(time_future)
- @next_time = Gitlab::Ci::CronParser.new(trigger_schedule.cron, trigger_schedule.cron_timezone).next_time_from(time_future)
+ trigger_schedule.update_column(:next_run_at, next_run_at)
end
it 'creates a new trigger request' do
- expect { worker.perform }.to change { Ci::TriggerRequest.count }.by(1)
+ expect { worker.perform }.to change { Ci::TriggerRequest.count }
end
it 'creates a new pipeline' do
- expect { worker.perform }.to change { Ci::Pipeline.count }.by(1)
+ expect { worker.perform }.to change { Ci::Pipeline.count }
expect(Ci::Pipeline.last).to be_pending
end
it 'updates next_run_at' do
- expect { worker.perform }.to change { Ci::TriggerSchedule.last.next_run_at }.to(@next_time)
+ worker.perform
+
+ expect(trigger_schedule.reload.next_run_at).not_to eq(next_run_at)
+ end
+
+ context 'inactive schedule' do
+ before do
+ trigger_schedule.update(active: false)
+ end
+
+ it 'does not create a new trigger' do
+ expect { worker.perform }.not_to change { Ci::TriggerRequest.count }
+ end
end
end
@@ -43,8 +58,8 @@ describe TriggerScheduleWorker do
context 'when next_run_at is nil' do
before do
- trigger_schedule = create(:ci_trigger_schedule, :nightly)
- trigger_schedule.update_attribute(:next_run_at, nil)
+ schedule = create(:ci_trigger_schedule, :nightly)
+ schedule.update_column(:next_run_at, nil)
end
it 'does not create a new pipeline' do