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:
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/admin/clusters_controller_spec.rb4
-rw-r--r--spec/controllers/concerns/send_file_upload_spec.rb2
-rw-r--r--spec/controllers/groups/clusters_controller_spec.rb4
-rw-r--r--spec/controllers/projects/branches_controller_spec.rb22
-rw-r--r--spec/controllers/projects/clusters_controller_spec.rb4
-rw-r--r--spec/controllers/projects/jobs_controller_spec.rb2
-rw-r--r--spec/controllers/projects/services_controller_spec.rb26
-rw-r--r--spec/db/schema_spec.rb1
-rw-r--r--spec/factories/ci/builds.rb20
-rw-r--r--spec/factories/clusters/kubernetes_namespaces.rb4
-rw-r--r--spec/factories/lfs_objects_projects.rb1
-rw-r--r--spec/factories/services.rb2
-rw-r--r--spec/factories/services_data.rb18
-rw-r--r--spec/factories/users.rb10
-rw-r--r--spec/features/commits_spec.rb6
-rw-r--r--spec/features/cycle_analytics_spec.rb2
-rw-r--r--spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb10
-rw-r--r--spec/features/projects/clusters/interchangeability_spec.rb16
-rw-r--r--spec/features/projects/commits/user_browses_commits_spec.rb2
-rw-r--r--spec/features/projects/environments/environment_spec.rb18
-rw-r--r--spec/features/projects/environments/environments_spec.rb18
-rw-r--r--spec/features/projects/jobs/user_browses_job_spec.rb46
-rw-r--r--spec/features/projects/jobs/user_browses_jobs_spec.rb6
-rw-r--r--spec/features/projects/jobs_spec.rb2
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb39
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb2
-rw-r--r--spec/finders/fork_projects_finder_spec.rb2
-rw-r--r--spec/finders/pipelines_finder_spec.rb5
-rw-r--r--spec/fixtures/trace/trace_with_duplicate_sections30
-rw-r--r--spec/javascripts/fixtures/pipelines.rb2
-rw-r--r--spec/javascripts/jobs/components/job_log_spec.js37
-rw-r--r--spec/javascripts/jobs/components/stages_dropdown_spec.js21
-rw-r--r--spec/javascripts/jobs/mock_data.js16
-rw-r--r--spec/javascripts/pipelines/mock_data.js1
-rw-r--r--spec/javascripts/pipelines/pipeline_url_spec.js5
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js28
-rw-r--r--spec/javascripts/vue_mr_widget/mock_data.js5
-rw-r--r--spec/javascripts/vue_mr_widget/mr_widget_options_spec.js2
-rw-r--r--spec/lib/gitlab/ci/ansi2html_spec.rb62
-rw-r--r--spec/lib/gitlab/ci/build/policy/kubernetes_spec.rb18
-rw-r--r--spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/build_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/lexeme/matches_spec.rb14
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb57
-rw-r--r--spec/lib/gitlab/ci/trace/stream_spec.rb15
-rw-r--r--spec/lib/gitlab/cycle_analytics/code_stage_spec.rb36
-rw-r--r--spec/lib/gitlab/cycle_analytics/events_spec.rb31
-rw-r--r--spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb31
-rw-r--r--spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb31
-rw-r--r--spec/lib/gitlab/cycle_analytics/review_stage_spec.rb37
-rw-r--r--spec/lib/gitlab/cycle_analytics/shared_stage_spec.rb2
-rw-r--r--spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb41
-rw-r--r--spec/lib/gitlab/gpg/commit_spec.rb83
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml2
-rw-r--r--spec/migrations/migrate_k8s_service_integration_spec.rb161
-rw-r--r--spec/models/ci/pipeline_spec.rb39
-rw-r--r--spec/models/clusters/cluster_spec.rb91
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb56
-rw-r--r--spec/models/environment_spec.rb42
-rw-r--r--spec/models/lfs_object_spec.rb14
-rw-r--r--spec/models/lfs_objects_project_spec.rb4
-rw-r--r--spec/models/project_services/hipchat_service_spec.rb2
-rw-r--r--spec/models/project_services/issue_tracker_data_spec.rb35
-rw-r--r--spec/models/project_services/jira_tracker_data_spec.rb42
-rw-r--r--spec/models/project_services/kubernetes_service_spec.rb44
-rw-r--r--spec/models/project_spec.rb62
-rw-r--r--spec/models/service_spec.rb8
-rw-r--r--spec/policies/project_policy_spec.rb2
-rw-r--r--spec/requests/api/container_registry_spec.rb6
-rw-r--r--spec/requests/api/graphql/tasks/task_completion_status_spec.rb60
-rw-r--r--spec/requests/api/services_spec.rb27
-rw-r--r--spec/requests/projects/cycle_analytics_events_spec.rb4
-rw-r--r--spec/serializers/environment_entity_spec.rb10
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb12
-rw-r--r--spec/services/ci/play_build_service_spec.rb37
-rw-r--r--spec/services/lfs/file_transformer_spec.rb60
-rw-r--r--spec/services/notification_service_spec.rb6
-rw-r--r--spec/services/projects/after_rename_service_spec.rb1
-rw-r--r--spec/services/projects/create_service_spec.rb29
-rw-r--r--spec/services/projects/fork_service_spec.rb3
-rw-r--r--spec/support/helpers/graphql_helpers.rb2
-rw-r--r--spec/support/helpers/query_recorder.rb2
-rw-r--r--spec/support/helpers/test_env.rb14
-rw-r--r--spec/support/prometheus/additional_metrics_shared_examples.rb17
-rw-r--r--spec/support/shared_contexts/services_shared_context.rb3
-rw-r--r--spec/support/shared_examples/ci_trace_shared_examples.rb4
-rw-r--r--spec/views/notify/pipeline_failed_email.html.haml_spec.rb2
-rw-r--r--spec/views/notify/pipeline_failed_email.text.erb_spec.rb2
-rw-r--r--spec/views/notify/pipeline_success_email.html.haml_spec.rb2
-rw-r--r--spec/views/projects/commit/_commit_box.html.haml_spec.rb4
-rw-r--r--spec/views/projects/jobs/_build.html.haml_spec.rb10
-rw-r--r--spec/workers/auto_devops/disable_worker_spec.rb3
-rw-r--r--spec/workers/reactive_caching_worker_spec.rb10
94 files changed, 1349 insertions, 496 deletions
diff --git a/spec/controllers/admin/clusters_controller_spec.rb b/spec/controllers/admin/clusters_controller_spec.rb
index 7b77cb186a4..7709f525119 100644
--- a/spec/controllers/admin/clusters_controller_spec.rb
+++ b/spec/controllers/admin/clusters_controller_spec.rb
@@ -396,6 +396,7 @@ describe Admin::ClustersController do
cluster: {
enabled: false,
name: 'my-new-cluster-name',
+ managed: false,
base_domain: domain
}
}
@@ -409,6 +410,7 @@ describe Admin::ClustersController do
expect(flash[:notice]).to eq('Kubernetes cluster was successfully updated.')
expect(cluster.enabled).to be_falsey
expect(cluster.name).to eq('my-new-cluster-name')
+ expect(cluster).not_to be_managed
expect(cluster.domain).to eq('test-domain.com')
end
@@ -433,6 +435,7 @@ describe Admin::ClustersController do
cluster: {
enabled: false,
name: 'my-new-cluster-name',
+ managed: false,
domain: domain
}
}
@@ -445,6 +448,7 @@ describe Admin::ClustersController do
expect(response).to have_http_status(:no_content)
expect(cluster.enabled).to be_falsey
expect(cluster.name).to eq('my-new-cluster-name')
+ expect(cluster).not_to be_managed
end
end
diff --git a/spec/controllers/concerns/send_file_upload_spec.rb b/spec/controllers/concerns/send_file_upload_spec.rb
index a3ce08f736c..3bf0ec799c7 100644
--- a/spec/controllers/concerns/send_file_upload_spec.rb
+++ b/spec/controllers/concerns/send_file_upload_spec.rb
@@ -115,7 +115,7 @@ describe SendFileUpload do
it 'sends a file with a custom type' do
headers = double
- expected_headers = /response-content-disposition=attachment%3B%20filename%3D%22test.js%22%3B%20filename%2A%3DUTF-8%27%27test.js&response-content-type=application%2Fecmascript/
+ expected_headers = /response-content-disposition=attachment%3B%20filename%3D%22test.js%22%3B%20filename%2A%3DUTF-8%27%27test.js&response-content-type=application%2Fjavascript/
expect(Gitlab::Workhorse).to receive(:send_url).with(expected_headers).and_call_original
expect(headers).to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-url:/)
diff --git a/spec/controllers/groups/clusters_controller_spec.rb b/spec/controllers/groups/clusters_controller_spec.rb
index 7349cb7094c..2f64c7f3460 100644
--- a/spec/controllers/groups/clusters_controller_spec.rb
+++ b/spec/controllers/groups/clusters_controller_spec.rb
@@ -463,6 +463,7 @@ describe Groups::ClustersController do
cluster: {
enabled: false,
name: 'my-new-cluster-name',
+ managed: false,
base_domain: domain
}
}
@@ -476,6 +477,7 @@ describe Groups::ClustersController do
expect(flash[:notice]).to eq('Kubernetes cluster was successfully updated.')
expect(cluster.enabled).to be_falsey
expect(cluster.name).to eq('my-new-cluster-name')
+ expect(cluster).not_to be_managed
expect(cluster.domain).to eq('test-domain.com')
end
@@ -500,6 +502,7 @@ describe Groups::ClustersController do
cluster: {
enabled: false,
name: 'my-new-cluster-name',
+ managed: false,
domain: domain
}
}
@@ -512,6 +515,7 @@ describe Groups::ClustersController do
expect(response).to have_http_status(:no_content)
expect(cluster.enabled).to be_falsey
expect(cluster.name).to eq('my-new-cluster-name')
+ expect(cluster).not_to be_managed
end
end
diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb
index c778b7888dc..cf201c9f735 100644
--- a/spec/controllers/projects/branches_controller_spec.rb
+++ b/spec/controllers/projects/branches_controller_spec.rb
@@ -123,7 +123,11 @@ describe Projects::BranchesController do
expect(response).to redirect_to project_tree_path(project, branch)
end
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
+ context 'when user configured kubernetes from CI/CD > Clusters' do
+ before do
+ create(:cluster, :provided_by_gcp, projects: [project])
+ end
+
it 'redirects to autodeploy setup page' do
result = { status: :success, branch: double(name: branch) }
@@ -143,22 +147,6 @@ describe Projects::BranchesController do
end
end
- context 'when user configured kubernetes from Integration > Kubernetes' do
- before do
- project.services << build(:kubernetes_service)
- end
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
- context 'when user configured kubernetes from CI/CD > Clusters' do
- before do
- create(:cluster, :provided_by_gcp, projects: [project])
- end
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
it 'redirects to autodeploy setup page' do
result = { status: :success, branch: double(name: branch) }
diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb
index 8d37bd82d21..fa49438287f 100644
--- a/spec/controllers/projects/clusters_controller_spec.rb
+++ b/spec/controllers/projects/clusters_controller_spec.rb
@@ -449,6 +449,7 @@ describe Projects::ClustersController do
cluster: {
enabled: false,
name: 'my-new-cluster-name',
+ managed: false,
platform_kubernetes_attributes: {
namespace: 'my-namespace'
}
@@ -464,6 +465,7 @@ describe Projects::ClustersController do
expect(flash[:notice]).to eq('Kubernetes cluster was successfully updated.')
expect(cluster.enabled).to be_falsey
expect(cluster.name).to eq('my-new-cluster-name')
+ expect(cluster).not_to be_managed
expect(cluster.platform_kubernetes.namespace).to eq('my-namespace')
end
@@ -475,6 +477,7 @@ describe Projects::ClustersController do
cluster: {
enabled: false,
name: 'my-new-cluster-name',
+ managed: false,
platform_kubernetes_attributes: {
namespace: 'my-namespace'
}
@@ -489,6 +492,7 @@ describe Projects::ClustersController do
expect(response).to have_http_status(:no_content)
expect(cluster.enabled).to be_falsey
expect(cluster.name).to eq('my-new-cluster-name')
+ expect(cluster).not_to be_managed
expect(cluster.platform_kubernetes.namespace).to eq('my-namespace')
end
end
diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb
index 490e9841492..0dabe27977a 100644
--- a/spec/controllers/projects/jobs_controller_spec.rb
+++ b/spec/controllers/projects/jobs_controller_spec.rb
@@ -540,7 +540,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['id']).to eq job.id
expect(json_response['status']).to eq job.status
- expect(json_response['html']).to eq('BUILD TRACE')
+ expect(json_response['html']).to eq('<span class="">BUILD TRACE</span>')
end
end
diff --git a/spec/controllers/projects/services_controller_spec.rb b/spec/controllers/projects/services_controller_spec.rb
index 3608d175d50..5c7f8d95f82 100644
--- a/spec/controllers/projects/services_controller_spec.rb
+++ b/spec/controllers/projects/services_controller_spec.rb
@@ -141,20 +141,6 @@ describe Projects::ServicesController do
end
end
- context 'with a deprecated service' do
- let(:service) { create(:kubernetes_service, project: project) }
-
- before do
- put :update,
- params: { namespace_id: project.namespace, project_id: project, id: service.to_param, service: { namespace: 'updated_namespace' } }
- end
-
- it 'does not update the service' do
- service.reload
- expect(service.namespace).not_to eq('updated_namespace')
- end
- end
-
context 'when activating JIRA service from a template' do
let(:template_service) { create(:jira_service, project: project, template: true) }
@@ -168,20 +154,10 @@ describe Projects::ServicesController do
describe "GET #edit" do
before do
- get :edit, params: { namespace_id: project.namespace, project_id: project, id: service_id }
+ get :edit, params: { namespace_id: project.namespace, project_id: project, id: 'jira' }
end
context 'with approved services' do
- let(:service_id) { 'jira' }
-
- it 'renders edit page' do
- expect(response).to be_success
- end
- end
-
- context 'with a deprecated service' do
- let(:service_id) { 'kubernetes' }
-
it 'renders edit page' do
expect(response).to be_success
end
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index 25616812814..6cfec5f4017 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -39,6 +39,7 @@ describe 'Database schema' do
geo_upload_deleted_events: %w[upload_id model_id],
identities: %w[user_id],
issues: %w[last_edited_by_id state_id],
+ jira_tracker_data: %w[jira_issue_transition_id],
keys: %w[user_id],
label_links: %w[target_id],
lfs_objects_projects: %w[lfs_object_id project_id],
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index a473136b57b..5f7c75a3a92 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -228,6 +228,26 @@ FactoryBot.define do
end
end
+ trait :trace_with_duplicate_sections do
+ after(:create) do |build, evaluator|
+ trace = File.binread(
+ File.expand_path(
+ Rails.root.join('spec/fixtures/trace/trace_with_duplicate_sections')))
+
+ build.trace.set(trace)
+ end
+ end
+
+ trait :trace_with_sections do
+ after(:create) do |build, evaluator|
+ trace = File.binread(
+ File.expand_path(
+ Rails.root.join('spec/fixtures/trace/trace_with_sections')))
+
+ build.trace.set(trace)
+ end
+ end
+
trait :unicode_trace_live do
after(:create) do |build, evaluator|
trace = File.binread(
diff --git a/spec/factories/clusters/kubernetes_namespaces.rb b/spec/factories/clusters/kubernetes_namespaces.rb
index 3b50a57433f..042be7b4c4a 100644
--- a/spec/factories/clusters/kubernetes_namespaces.rb
+++ b/spec/factories/clusters/kubernetes_namespaces.rb
@@ -16,5 +16,9 @@ FactoryBot.define do
trait :with_token do
service_account_token { FFaker::Lorem.characters(10) }
end
+
+ trait :without_token do
+ service_account_token nil
+ end
end
end
diff --git a/spec/factories/lfs_objects_projects.rb b/spec/factories/lfs_objects_projects.rb
index c225387a5de..4804d0bb884 100644
--- a/spec/factories/lfs_objects_projects.rb
+++ b/spec/factories/lfs_objects_projects.rb
@@ -2,5 +2,6 @@ FactoryBot.define do
factory :lfs_objects_project do
lfs_object
project
+ repository_type :project
end
end
diff --git a/spec/factories/services.rb b/spec/factories/services.rb
index 0d8c26a2ee9..763909f30bd 100644
--- a/spec/factories/services.rb
+++ b/spec/factories/services.rb
@@ -24,6 +24,8 @@ FactoryBot.define do
api_url: 'https://kubernetes.example.com',
token: 'a' * 40
})
+
+ skip_deprecation_validation true
end
factory :mock_deployment_service do
diff --git a/spec/factories/services_data.rb b/spec/factories/services_data.rb
new file mode 100644
index 00000000000..387e130a743
--- /dev/null
+++ b/spec/factories/services_data.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :jira_tracker_data do
+ service
+ url 'http://jira.example.com'
+ api_url 'http://api-jira.example.com'
+ username 'jira_username'
+ password 'jira_password'
+ end
+
+ factory :issue_tracker_data do
+ service
+ project_url 'http://issuetracker.example.com'
+ issues_url 'http://issues.example.com'
+ new_issue_url 'http://new-issue.example.com'
+ end
+end
diff --git a/spec/factories/users.rb b/spec/factories/users.rb
index 1d2b724a5e5..4f3392cdcbf 100644
--- a/spec/factories/users.rb
+++ b/spec/factories/users.rb
@@ -66,6 +66,16 @@ FactoryBot.define do
end
end
+ transient do
+ developer_projects []
+ end
+
+ after(:create) do |user, evaluator|
+ evaluator.developer_projects.each do |project|
+ project.add_developer(user)
+ end
+ end
+
factory :omniauth_user do
transient do
extern_uid '123456'
diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb
index e6f44aa7d20..a2dd34e7f7c 100644
--- a/spec/features/commits_spec.rb
+++ b/spec/features/commits_spec.rb
@@ -10,8 +10,7 @@ describe 'Commits' do
stub_ci_pipeline_to_return_yaml_file
end
- let(:creator) { create(:user) }
-
+ let(:creator) { create(:user, developer_projects: [project]) }
let!(:pipeline) do
create(:ci_pipeline,
project: project,
@@ -77,10 +76,11 @@ describe 'Commits' do
describe 'Commit builds', :js do
before do
+ project.add_developer(user)
visit pipeline_path(pipeline)
end
- it 'shows pipeline`s data' do
+ it 'shows pipeline data' do
expect(page).to have_content pipeline.sha[0..7]
expect(page).to have_content pipeline.git_commit_message.gsub!(/\s+/, ' ')
expect(page).to have_content pipeline.user.name
diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb
index 48edc764a8e..4108a0f370d 100644
--- a/spec/features/cycle_analytics_spec.rb
+++ b/spec/features/cycle_analytics_spec.rb
@@ -58,7 +58,7 @@ describe 'Cycle Analytics', :js do
expect_issue_to_be_present
click_stage('Plan')
- expect(find('.stage-events')).to have_content(mr.commits.last.title)
+ expect_issue_to_be_present
click_stage('Code')
expect_merge_request_to_be_present
diff --git a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
index 586b3ba170d..85c4d778fd0 100644
--- a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
+++ b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
@@ -52,7 +52,7 @@ describe 'Merge request > User merges when pipeline succeeds', :js do
# so we have to wait for asynchronous call to reload it
# and have_content expectation handles that.
#
- expect(page).to have_content "Pipeline ##{pipeline.id} (##{pipeline.iid}) running"
+ expect(page).to have_content "Pipeline ##{pipeline.id} running"
end
it_behaves_like 'Merge when pipeline succeeds activator'
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index 393077a916f..733e8aa3eba 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -160,7 +160,7 @@ describe 'Merge request > User sees merge widget', :js do
it 'shows head pipeline information' do
within '.ci-widget-content' do
- expect(page).to have_content("Pipeline ##{pipeline.id} (##{pipeline.iid}) pending " \
+ expect(page).to have_content("Pipeline ##{pipeline.id} pending " \
"for #{pipeline.short_sha} " \
"on #{pipeline.ref}")
end
@@ -189,7 +189,7 @@ describe 'Merge request > User sees merge widget', :js do
it 'shows head pipeline information' do
within '.ci-widget-content' do
- expect(page).to have_content("Pipeline ##{pipeline.id} (##{pipeline.iid}) pending " \
+ expect(page).to have_content("Pipeline ##{pipeline.id} pending " \
"for #{pipeline.short_sha} " \
"on #{merge_request.to_reference} " \
"with #{merge_request.source_branch}")
@@ -201,7 +201,7 @@ describe 'Merge request > User sees merge widget', :js do
it 'shows head pipeline information' do
within '.ci-widget-content' do
- expect(page).to have_content("Pipeline ##{pipeline.id} (##{pipeline.iid}) pending " \
+ expect(page).to have_content("Pipeline ##{pipeline.id} pending " \
"for #{pipeline.short_sha} " \
"on #{merge_request.to_reference} " \
"with #{merge_request.source_branch}")
@@ -234,7 +234,7 @@ describe 'Merge request > User sees merge widget', :js do
it 'shows head pipeline information' do
within '.ci-widget-content' do
- expect(page).to have_content("Pipeline ##{pipeline.id} (##{pipeline.iid}) pending " \
+ expect(page).to have_content("Pipeline ##{pipeline.id} pending " \
"for #{pipeline.short_sha} " \
"on #{merge_request.to_reference} " \
"with #{merge_request.source_branch} " \
@@ -248,7 +248,7 @@ describe 'Merge request > User sees merge widget', :js do
it 'shows head pipeline information' do
within '.ci-widget-content' do
- expect(page).to have_content("Pipeline ##{pipeline.id} (##{pipeline.iid}) pending " \
+ expect(page).to have_content("Pipeline ##{pipeline.id} pending " \
"for #{pipeline.short_sha} " \
"on #{merge_request.to_reference} " \
"with #{merge_request.source_branch} " \
diff --git a/spec/features/projects/clusters/interchangeability_spec.rb b/spec/features/projects/clusters/interchangeability_spec.rb
deleted file mode 100644
index 0033e12b6b1..00000000000
--- a/spec/features/projects/clusters/interchangeability_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require 'spec_helper'
-
-describe 'Interchangeability between KubernetesService and Platform::Kubernetes' do
- EXCEPT_METHODS = %i[test title description help fields initialize_properties namespace namespace= api_url api_url= deprecated? deprecation_message].freeze
- EXCEPT_METHODS_GREP_V = %w[_touched? _changed? _was].freeze
-
- it 'Clusters::Platform::Kubernetes covers core interfaces in KubernetesService' do
- expected_interfaces = KubernetesService.instance_methods(false)
- expected_interfaces = expected_interfaces - EXCEPT_METHODS
- EXCEPT_METHODS_GREP_V.each do |g|
- expected_interfaces = expected_interfaces.grep_v(/#{Regexp.escape(g)}\z/)
- end
-
- expect(expected_interfaces - Clusters::Platforms::Kubernetes.instance_methods).to be_empty
- end
-end
diff --git a/spec/features/projects/commits/user_browses_commits_spec.rb b/spec/features/projects/commits/user_browses_commits_spec.rb
index a84fee34669..fc74a370e72 100644
--- a/spec/features/projects/commits/user_browses_commits_spec.rb
+++ b/spec/features/projects/commits/user_browses_commits_spec.rb
@@ -61,7 +61,7 @@ describe 'User browses commits' do
it 'renders commit ci info' do
visit project_commit_path(project, sample_commit.id)
- expect(page).to have_content "Pipeline ##{pipeline.id} (##{pipeline.iid}) pending"
+ expect(page).to have_content "Pipeline ##{pipeline.id} pending"
end
end
diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb
index da4ef6428d4..fbaf12be64e 100644
--- a/spec/features/projects/environments/environment_spec.rb
+++ b/spec/features/projects/environments/environment_spec.rb
@@ -155,7 +155,10 @@ describe 'Environment' do
end
context 'with terminal' do
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
+ context 'when user configured kubernetes from CI/CD > Clusters' do
+ let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.project }
+
context 'for project maintainer' do
let(:role) { :maintainer }
@@ -191,19 +194,6 @@ describe 'Environment' do
end
end
end
-
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project, :test_repo) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
- context 'when user configured kubernetes from CI/CD > Clusters' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:project) { cluster.project }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
end
context 'when environment is available' do
diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb
index 7b7e45312d9..1b5d9083932 100644
--- a/spec/features/projects/environments/environments_spec.rb
+++ b/spec/features/projects/environments/environments_spec.rb
@@ -248,7 +248,10 @@ describe 'Environments page', :js do
end
context 'when kubernetes terminal is available' do
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
+ context 'when user configured kubernetes from CI/CD > Clusters' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, projects: [create(:project, :repository)]) }
+ let(:project) { cluster.project }
+
context 'for project maintainer' do
let(:role) { :maintainer }
@@ -265,19 +268,6 @@ describe 'Environments page', :js do
end
end
end
-
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project, :test_repo) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
- context 'when user configured kubernetes from CI/CD > Clusters' do
- let(:cluster) { create(:cluster, :provided_by_gcp, projects: [create(:project, :repository)]) }
- let(:project) { cluster.project }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
end
end
diff --git a/spec/features/projects/jobs/user_browses_job_spec.rb b/spec/features/projects/jobs/user_browses_job_spec.rb
index 54b462da87a..fbe765d4c44 100644
--- a/spec/features/projects/jobs/user_browses_job_spec.rb
+++ b/spec/features/projects/jobs/user_browses_job_spec.rb
@@ -34,6 +34,52 @@ describe 'User browses a job', :js do
expect(page).to have_content('Job has been erased')
end
+ shared_examples 'has collapsible sections' do
+ it 'collapses the section clicked' do
+ wait_for_requests
+ text_to_hide = "Cloning into '/nolith/ci-tests'"
+ text_to_show = 'Waiting for pod'
+
+ expect(page).to have_content(text_to_hide)
+ expect(page).to have_content(text_to_show)
+
+ first('.js-section-start[data-section="get-sources"]').click
+
+ expect(page).not_to have_content(text_to_hide)
+ expect(page).to have_content(text_to_show)
+ end
+ end
+
+ context 'when job trace contains sections' do
+ let!(:build) { create(:ci_build, :success, :trace_with_sections, :coverage, pipeline: pipeline) }
+
+ it_behaves_like 'has collapsible sections'
+ end
+
+ context 'when job trace contains duplicate sections' do
+ let!(:build) { create(:ci_build, :success, :trace_with_duplicate_sections, :coverage, pipeline: pipeline) }
+
+ it_behaves_like 'has collapsible sections'
+ end
+
+ context 'when job trace contains sections' do
+ let!(:build) { create(:ci_build, :success, :trace_with_duplicate_sections, :coverage, pipeline: pipeline) }
+
+ it 'collapses a section' do
+ wait_for_requests
+ text_to_hide = "Cloning into '/nolith/ci-tests'"
+ text_to_show = 'Waiting for pod'
+
+ expect(page).to have_content(text_to_hide)
+ expect(page).to have_content(text_to_show)
+
+ first('.js-section-start[data-section="get-sources"]').click
+
+ expect(page).not_to have_content(text_to_hide)
+ expect(page).to have_content(text_to_show)
+ end
+ end
+
context 'with a failed job' do
let!(:build) { create(:ci_build, :failed, :trace_artifact, pipeline: pipeline) }
diff --git a/spec/features/projects/jobs/user_browses_jobs_spec.rb b/spec/features/projects/jobs/user_browses_jobs_spec.rb
index bd6c73f4b85..ebc20d15d67 100644
--- a/spec/features/projects/jobs/user_browses_jobs_spec.rb
+++ b/spec/features/projects/jobs/user_browses_jobs_spec.rb
@@ -16,12 +16,6 @@ describe 'User browses jobs' do
visit(project_jobs_path(project))
end
- it 'shows pipeline id and IID' do
- page.within('td.pipeline-link') do
- expect(page).to have_content("##{pipeline.id} (##{pipeline.iid})")
- end
- end
-
it 'shows the coverage' do
page.within('td.coverage') do
expect(page).to have_content('99.9%')
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index 03562bd382e..f4ed89adc0f 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -129,7 +129,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
visit project_job_path(project, job)
within '.js-pipeline-info' do
- expect(page).to have_content("Pipeline ##{pipeline.id} (##{pipeline.iid}) for #{pipeline.ref}")
+ expect(page).to have_content("Pipeline ##{pipeline.id} for #{pipeline.ref}")
end
end
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index 77f0f237d0a..9759fd04ad2 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
describe 'Pipeline', :js do
include RoutesHelpers
include ProjectForksHelper
+ include ::ExclusiveLeaseHelpers
let(:project) { create(:project) }
let(:user) { create(:user) }
@@ -539,6 +540,44 @@ describe 'Pipeline', :js do
expect(page).to have_selector('.pipeline-visualization')
expect(page).to have_content('cross-build')
end
+
+ context 'when a scheduled pipeline is created by a blocked user' do
+ let(:project) { create(:project, :repository) }
+
+ let(:schedule) do
+ create(:ci_pipeline_schedule,
+ project: project,
+ owner: project.owner,
+ description: 'blocked user schedule'
+ ).tap do |schedule|
+ schedule.update_column(:next_run_at, 1.minute.ago)
+ end
+ end
+
+ before do
+ schedule.owner.block!
+
+ begin
+ PipelineScheduleWorker.new.perform
+ rescue Ci::CreatePipelineService::CreateError
+ # Do nothing, assert view code after the Pipeline failed to create.
+ end
+ end
+
+ it 'displays the PipelineSchedule in an active state' do
+ visit project_pipeline_schedules_path(project)
+ page.click_link('Active')
+
+ expect(page).to have_selector('table.ci-table > tbody > tr > td', text: 'blocked user schedule')
+ end
+
+ it 'does not create a new Pipeline' do
+ visit project_pipelines_path(project)
+
+ expect(page).not_to have_selector('.ci-table')
+ expect(schedule.last_pipeline).to be_nil
+ end
+ end
end
describe 'GET /:project/pipelines/:id/builds' do
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index de780f13681..885d5f85989 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -469,7 +469,7 @@ describe 'Pipelines', :js do
visit_project_pipelines
end
- it 'has artifats' do
+ it 'has artifacts' do
expect(page).to have_selector('.build-artifacts')
end
diff --git a/spec/finders/fork_projects_finder_spec.rb b/spec/finders/fork_projects_finder_spec.rb
index b3fdffc3331..98cff37205e 100644
--- a/spec/finders/fork_projects_finder_spec.rb
+++ b/spec/finders/fork_projects_finder_spec.rb
@@ -12,6 +12,8 @@ describe ForkProjectsFinder do
let(:private_fork_member) { create(:user) }
before do
+ stub_feature_flags(object_pools: { enabled: false, thing: source_project })
+
private_fork.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
private_fork.add_developer(private_fork_member)
diff --git a/spec/finders/pipelines_finder_spec.rb b/spec/finders/pipelines_finder_spec.rb
index c2c304589c9..b23fd8ccdc6 100644
--- a/spec/finders/pipelines_finder_spec.rb
+++ b/spec/finders/pipelines_finder_spec.rb
@@ -170,8 +170,9 @@ describe PipelinesFinder do
context 'when order_by and sort are specified' do
context 'when order_by user_id' do
- let(:params) { { order_by: 'user_id', sort: 'asc' } }
- let!(:pipelines) { Array.new(2) { create(:ci_pipeline, project: project, user: create(:user)) } }
+ let(:params) { { order_by: 'user_id', sort: 'asc' } }
+ let(:users) { Array.new(2) { create(:user, developer_projects: [project]) } }
+ let!(:pipelines) { users.map { |user| create(:ci_pipeline, project: project, user: user) } }
it 'sorts as user_id: :asc' do
is_expected.to match_array(pipelines)
diff --git a/spec/fixtures/trace/trace_with_duplicate_sections b/spec/fixtures/trace/trace_with_duplicate_sections
new file mode 100644
index 00000000000..7a894e80e38
--- /dev/null
+++ b/spec/fixtures/trace/trace_with_duplicate_sections
@@ -0,0 +1,30 @@
+Running with gitlab-runner dev (HEAD)
+ on kitsune minikube (a21b584f)
+WARNING: Namespace is empty, therefore assuming 'default'.
+Using Kubernetes namespace: default
+Using Kubernetes executor with image alpine:3.4 ...
+section_start:1506004954:prepare_script Waiting for pod default/runner-a21b584f-project-1208199-concurrent-0sg03f to be running, status is Pending
+Running on runner-a21b584f-project-1208199-concurrent-0sg03f via kitsune.local...
+section_end:1506004957:prepare_script section_start:1506004957:get_sources Cloning repository...
+Cloning into '/nolith/ci-tests'...
+Checking out dddd7a6e as master...
+Skipping Git submodules setup
+section_end:1506004958:get_sources section_start:1506004958:restore_cache section_end:1506004958:restore_cache section_start:1506004958:download_artifacts section_end:1506004958:download_artifacts section_start:1506004958:build_script $ whoami
+root
+section_end:1506004959:build_script section_start:1506004959:after_script section_end:1506004959:after_script section_start:1506004959:archive_cache section_end:1506004959:archive_cache section_start:1506004959:upload_artifacts section_end:1506004959:upload_artifacts Job succeeded
+
+Running with gitlab-runner dev (HEAD)
+ on kitsune minikube (a21b584f)
+WARNING: Namespace is empty, therefore assuming 'default'.
+Using Kubernetes namespace: default
+Using Kubernetes executor with image alpine:3.4 ...
+section_start:1506004954:prepare_script Waiting for pod default/runner-a21b584f-project-1208199-concurrent-0sg03f to be running, status is Pending
+Running on runner-a21b584f-project-1208199-concurrent-0sg03f via kitsune.local...
+section_end:1506004957:prepare_script section_start:1506004957:get_sources Cloning repository...
+Cloning into '/nolith/ci-tests'...
+Checking out dddd7a6e as master...
+Skipping Git submodules setup
+section_end:1506004958:get_sources section_start:1506004958:restore_cache section_end:1506004958:restore_cache section_start:1506004958:download_artifacts section_end:1506004958:download_artifacts section_start:1506004958:build_script $ whoami
+root
+section_end:1506004959:build_script section_start:1506004959:after_script section_end:1506004959:after_script section_start:1506004959:archive_cache section_end:1506004959:archive_cache section_start:1506004959:upload_artifacts section_end:1506004959:upload_artifacts Job succeeded
+
diff --git a/spec/javascripts/fixtures/pipelines.rb b/spec/javascripts/fixtures/pipelines.rb
index de6fcfe10f4..6b6b0eefab9 100644
--- a/spec/javascripts/fixtures/pipelines.rb
+++ b/spec/javascripts/fixtures/pipelines.rb
@@ -8,7 +8,7 @@ describe Projects::PipelinesController, '(JavaScript fixtures)', type: :controll
let(:project) { create(:project, :repository, namespace: namespace, path: 'pipelines-project') }
let(:commit) { create(:commit, project: project) }
let(:commit_without_author) { RepoHelpers.another_sample_commit }
- let!(:user) { create(:user, email: commit.author_email) }
+ let!(:user) { create(:user, developer_projects: [project], email: commit.author_email) }
let!(:pipeline) { create(:ci_pipeline, project: project, sha: commit.id, user: user) }
let!(:pipeline_without_author) { create(:ci_pipeline, project: project, sha: commit_without_author.id) }
let!(:pipeline_without_commit) { create(:ci_pipeline, project: project, sha: '0000') }
diff --git a/spec/javascripts/jobs/components/job_log_spec.js b/spec/javascripts/jobs/components/job_log_spec.js
index dc0f77ceb80..7e2ec2ec3f7 100644
--- a/spec/javascripts/jobs/components/job_log_spec.js
+++ b/spec/javascripts/jobs/components/job_log_spec.js
@@ -3,6 +3,7 @@ import component from '~/jobs/components/job_log.vue';
import createStore from '~/jobs/store';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { resetStore } from '../store/helpers';
+import { logWithCollapsibleSections } from '../mock_data';
describe('Job Log', () => {
const Component = Vue.extend(component);
@@ -62,4 +63,40 @@ describe('Job Log', () => {
expect(vm.$el.querySelector('.js-log-animation')).toBeNull();
});
});
+
+ describe('Collapsible sections', () => {
+ beforeEach(() => {
+ vm = mountComponentWithStore(Component, {
+ props: {
+ trace: logWithCollapsibleSections.html,
+ isComplete: true,
+ },
+ store,
+ });
+ });
+
+ it('renders open arrow', () => {
+ expect(vm.$el.querySelector('.fa-caret-down')).not.toBeNull();
+ });
+
+ it('toggles hidden class to the sibilings rows when arrow is clicked', done => {
+ vm.$nextTick()
+ .then(() => {
+ const { section } = vm.$el.querySelector('.js-section-start').dataset;
+ vm.$el.querySelector('.js-section-start').click();
+
+ vm.$el.querySelectorAll(`.js-s-${section}:not(.js-section-header)`).forEach(el => {
+ expect(el.classList.contains('hidden')).toEqual(true);
+ });
+
+ vm.$el.querySelector('.js-section-start').click();
+
+ vm.$el.querySelectorAll(`.js-s-${section}:not(.js-section-header)`).forEach(el => {
+ expect(el.classList.contains('hidden')).toEqual(false);
+ });
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
});
diff --git a/spec/javascripts/jobs/components/stages_dropdown_spec.js b/spec/javascripts/jobs/components/stages_dropdown_spec.js
index e98639bf21e..52bb5161123 100644
--- a/spec/javascripts/jobs/components/stages_dropdown_spec.js
+++ b/spec/javascripts/jobs/components/stages_dropdown_spec.js
@@ -9,7 +9,6 @@ describe('Stages Dropdown', () => {
const mockPipelineData = {
id: 28029444,
- iid: 123,
details: {
status: {
details_path: '/gitlab-org/gitlab-ce/pipelines/28029444',
@@ -78,8 +77,8 @@ describe('Stages Dropdown', () => {
expect(vm.$el.querySelector('.dropdown .js-selected-stage').textContent).toContain('deploy');
});
- it(`renders the pipeline info text like "Pipeline #123 (#12) for source_branch"`, () => {
- const expected = `Pipeline #${pipeline.id} (#${pipeline.iid}) for ${pipeline.ref.name}`;
+ it(`renders the pipeline info text like "Pipeline #123 for source_branch"`, () => {
+ const expected = `Pipeline #${pipeline.id} for ${pipeline.ref.name}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
expect(actual).toBe(expected);
@@ -101,10 +100,10 @@ describe('Stages Dropdown', () => {
});
});
- it(`renders the pipeline info text like "Pipeline #123 (#12) for !456 with source_branch into target_branch"`, () => {
- const expected = `Pipeline #${pipeline.id} (#${pipeline.iid}) for !${
- pipeline.merge_request.iid
- } with ${pipeline.merge_request.source_branch} into ${pipeline.merge_request.target_branch}`;
+ it(`renders the pipeline info text like "Pipeline #123 for !456 with source_branch into target_branch"`, () => {
+ const expected = `Pipeline #${pipeline.id} for !${pipeline.merge_request.iid} with ${
+ pipeline.merge_request.source_branch
+ } into ${pipeline.merge_request.target_branch}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
expect(actual).toBe(expected);
@@ -144,10 +143,10 @@ describe('Stages Dropdown', () => {
});
});
- it(`renders the pipeline info like "Pipeline #123 (#12) for !456 with source_branch"`, () => {
- const expected = `Pipeline #${pipeline.id} (#${pipeline.iid}) for !${
- pipeline.merge_request.iid
- } with ${pipeline.merge_request.source_branch}`;
+ it(`renders the pipeline info like "Pipeline #123 for !456 with source_branch"`, () => {
+ const expected = `Pipeline #${pipeline.id} for !${pipeline.merge_request.iid} with ${
+ pipeline.merge_request.source_branch
+ }`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
expect(actual).toBe(expected);
diff --git a/spec/javascripts/jobs/mock_data.js b/spec/javascripts/jobs/mock_data.js
index 88b0bb206ee..c5022d3e93d 100644
--- a/spec/javascripts/jobs/mock_data.js
+++ b/spec/javascripts/jobs/mock_data.js
@@ -960,7 +960,6 @@ export default {
},
pipeline: {
id: 140,
- iid: 13,
user: {
name: 'Root',
username: 'root',
@@ -1190,3 +1189,18 @@ export const jobsInStage = {
path: '/gitlab-org/gitlab-shell/pipelines/27#build',
dropdown_path: '/gitlab-org/gitlab-shell/pipelines/27/stage.json?stage=build',
};
+
+export const logWithCollapsibleSections = {
+ append: false,
+ complete: true,
+ html:
+ '<div class="js-section-start fa fa-caret-down append-right-8 cursor-pointer" data-timestamp="1559571405" data-section="after-script" role="button"></div><span class="term-fg-l-green term-bold section js-section-header js-s-after-script">Running after script...</span><span class="section js-section-header js-s-after-script"><br /></span><span class="section s_after-script line"></span><span class="section js-s-after-script"></span><span class="term-fg-l-green term-bold section js-s-after-script">$ date</span><span class="section js-s-after-script"><br /></span><span class="section s_after-script line"></span><span class="section js-s-after-script">Mon Jun 3 14:16:46 UTC 2019<br /></span><span class="section s_after-script line"></span><span class="section js-s-after-script"></span><div class="section-end" data-section="after-script"></div><div class="js-section-start fa fa-caret-down append-right-8 cursor-pointer"data-timestamp="1559571408" data-section="archive-cache" role="button" ></div><span class="term-fg-l-green term-bold section js-section-header js-s-archive-cache">Not uploading cache debian-stretch-ruby-2.6.3-node-10.x-3 due to policy</span><span class="section js-section-header js-s-archive-cache"><br /></span><span class="section s_archive-cache line"></span><span class="section js-s-archive-cache"></span><div class="section-end" data-section="archive-cache"></div><div class="js-section-start fa fa-caret-down append-right-8 cursor-pointer" data-timestamp="1559571409" data-section="upload-artifacts-on-success" role="button"></div><span class="term-fg-l-green term-bold section js-section-header js-s-upload-artifacts-on-success">Uploading artifacts...</span><span class="section js-section-header js-s-upload-artifacts-on-success"><br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success">coverage/: found 5 matching files </span><span class="section js-s-upload-artifacts-on-success"> <br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success">knapsack/: found 4 matching files </span><span class="section js-s-upload-artifacts-on-success"> <br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success">rspec_flaky/: found 4 matching files </span><span class="section js-s-upload-artifacts-on-success"> <br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success">rspec_profiling/: found 1 matching files </span><span class="section js-s-upload-artifacts-on-success"> <br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success"></span><span class="term-fg-yellow section js-s-upload-artifacts-on-success">WARNING: tmp/capybara/: no matching files </span><span class="section js-s-upload-artifacts-on-success"> <br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success">Uploading artifacts to coordinator... ok </span><span class="section js-s-upload-artifacts-on-success"> id</span><span class="section js-s-upload-artifacts-on-success">=224162288 responseStatus</span><span class="section js-s-upload-artifacts-on-success">=201 Created token</span><span class="section js-s-upload-artifacts-on-success">=bBmyXJNW<br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success"></span><span class="term-fg-l-green term-bold section js-s-upload-artifacts-on-success">Uploading artifacts...</span><span class="section js-s-upload-artifacts-on-success"><br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success">junit_rspec.xml: found 1 matching files </span><span class="section js-s-upload-artifacts-on-success"> <br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success">Uploading artifacts to coordinator... ok </span><span class="section js-s-upload-artifacts-on-success"> id</span><span class="section js-s-upload-artifacts-on-success">=224162288 responseStatus</span><span class="section js-s-upload-artifacts-on-success">=201 Created token</span><span class="section js-s-upload-artifacts-on-success">=bBmyXJNW<br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success"></span><div class="section-end" data-section="upload-artifacts-on-success"></div><span class="term-fg-l-green term-bold">Job succeeded<br /><span class="term-fg-l-green term-bold"></span></span>',
+ id: 1385,
+ offset: 0,
+ size: 78815,
+ state:
+ 'eyJvZmZzZXQiOjc4ODE1LCJuX29wZW5fdGFncyI6MCwiZmdfY29sb3IiOm51bGwsImJnX2NvbG9yIjpudWxsLCJzdHlsZV9tYXNrIjowLCJzZWN0aW9ucyI6W10sImxpbmVub19pbl9zZWN0aW9uIjoxMX0=',
+ status: 'success',
+ total: 78815,
+ truncated: false,
+};
diff --git a/spec/javascripts/pipelines/mock_data.js b/spec/javascripts/pipelines/mock_data.js
index 8eef9166b8d..03ead6cd8ba 100644
--- a/spec/javascripts/pipelines/mock_data.js
+++ b/spec/javascripts/pipelines/mock_data.js
@@ -1,6 +1,5 @@
export const pipelineWithStages = {
id: 20333396,
- iid: 304399,
user: {
id: 128633,
name: 'Rémy Coutable',
diff --git a/spec/javascripts/pipelines/pipeline_url_spec.js b/spec/javascripts/pipelines/pipeline_url_spec.js
index 88c0137dc58..aa196af2f33 100644
--- a/spec/javascripts/pipelines/pipeline_url_spec.js
+++ b/spec/javascripts/pipelines/pipeline_url_spec.js
@@ -13,7 +13,6 @@ describe('Pipeline Url Component', () => {
propsData: {
pipeline: {
id: 1,
- iid: 1,
path: 'foo',
flags: {},
},
@@ -29,7 +28,6 @@ describe('Pipeline Url Component', () => {
propsData: {
pipeline: {
id: 1,
- iid: 1,
path: 'foo',
flags: {},
},
@@ -49,7 +47,6 @@ describe('Pipeline Url Component', () => {
propsData: {
pipeline: {
id: 1,
- iid: 1,
path: 'foo',
flags: {
latest: true,
@@ -81,7 +78,6 @@ describe('Pipeline Url Component', () => {
propsData: {
pipeline: {
id: 1,
- iid: 1,
path: 'foo',
flags: {
latest: true,
@@ -104,7 +100,6 @@ describe('Pipeline Url Component', () => {
propsData: {
pipeline: {
id: 1,
- iid: 1,
path: 'foo',
flags: {
failure_reason: true,
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
index a2308b0dfdb..75017d20473 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
@@ -103,7 +103,7 @@ describe('MRWidgetPipeline', () => {
it('should render pipeline ID', () => {
expect(vm.$el.querySelector('.pipeline-id').textContent.trim()).toEqual(
- `#${mockData.pipeline.id} (#${mockData.pipeline.iid})`,
+ `#${mockData.pipeline.id}`,
);
});
@@ -150,7 +150,7 @@ describe('MRWidgetPipeline', () => {
it('should render pipeline ID', () => {
expect(vm.$el.querySelector('.pipeline-id').textContent.trim()).toEqual(
- `#${mockData.pipeline.id} (#${mockData.pipeline.iid})`,
+ `#${mockData.pipeline.id}`,
);
});
@@ -222,9 +222,9 @@ describe('MRWidgetPipeline', () => {
sourceBranchLink: mockCopy.source_branch_link,
});
- const expected = `Pipeline #${pipeline.id} (#${pipeline.iid}) ${
- pipeline.details.status.label
- } for ${pipeline.commit.short_id} on ${mockCopy.source_branch_link}`;
+ const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${
+ pipeline.commit.short_id
+ } on ${mockCopy.source_branch_link}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info-container').innerText);
@@ -247,11 +247,11 @@ describe('MRWidgetPipeline', () => {
sourceBranchLink: mockCopy.source_branch_link,
});
- const expected = `Pipeline #${pipeline.id} (#${pipeline.iid}) ${
- pipeline.details.status.label
- } for ${pipeline.commit.short_id} on !${pipeline.merge_request.iid} with ${
- pipeline.merge_request.source_branch
- } into ${pipeline.merge_request.target_branch}`;
+ const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${
+ pipeline.commit.short_id
+ } on !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch} into ${
+ pipeline.merge_request.target_branch
+ }`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info-container').innerText);
@@ -274,11 +274,9 @@ describe('MRWidgetPipeline', () => {
sourceBranchLink: mockCopy.source_branch_link,
});
- const expected = `Pipeline #${pipeline.id} (#${pipeline.iid}) ${
- pipeline.details.status.label
- } for ${pipeline.commit.short_id} on !${pipeline.merge_request.iid} with ${
- pipeline.merge_request.source_branch
- }`;
+ const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${
+ pipeline.commit.short_id
+ } on !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info-container').innerText);
diff --git a/spec/javascripts/vue_mr_widget/mock_data.js b/spec/javascripts/vue_mr_widget/mock_data.js
index 3c9a5cece90..48f812f0db4 100644
--- a/spec/javascripts/vue_mr_widget/mock_data.js
+++ b/spec/javascripts/vue_mr_widget/mock_data.js
@@ -61,7 +61,6 @@ export default {
"Merge branch 'daaaa' into 'master'\n\nUpdate README.md\n\nSee merge request !22",
pipeline: {
id: 172,
- iid: 32,
user: {
name: 'Administrator',
username: 'root',
@@ -243,8 +242,6 @@ export default {
export const mockStore = {
pipeline: {
id: 0,
- iid: 0,
- path: '/root/acets-app/pipelines/0',
details: {
status: {
details_path: '/root/review-app-tester/pipelines/66',
@@ -262,8 +259,6 @@ export const mockStore = {
},
mergePipeline: {
id: 1,
- iid: 1,
- path: '/root/acets-app/pipelines/0',
details: {
status: {
details_path: '/root/review-app-tester/pipelines/66',
diff --git a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
index 08f7a17515e..ac2fb16bd10 100644
--- a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
@@ -544,7 +544,6 @@ describe('mrWidgetOptions', () => {
];
const deploymentMockData = {
id: 15,
- iid: 7,
name: 'review/diplo',
url: '/root/acets-review-apps/environments/15',
stop_url: '/root/acets-review-apps/environments/15/stop',
@@ -591,7 +590,6 @@ describe('mrWidgetOptions', () => {
vm.mr.state = 'merged';
vm.mr.mergePipeline = {
id: 127,
- iid: 35,
user: {
id: 1,
name: 'Administrator',
diff --git a/spec/lib/gitlab/ci/ansi2html_spec.rb b/spec/lib/gitlab/ci/ansi2html_spec.rb
index 5a5c071c639..ac4612dda92 100644
--- a/spec/lib/gitlab/ci/ansi2html_spec.rb
+++ b/spec/lib/gitlab/ci/ansi2html_spec.rb
@@ -4,11 +4,11 @@ describe Gitlab::Ci::Ansi2html do
subject { described_class }
it "prints non-ansi as-is" do
- expect(convert_html("Hello")).to eq('Hello')
+ expect(convert_html("Hello")).to eq('<span class="">Hello</span>')
end
it "strips non-color-changing control sequences" do
- expect(convert_html("Hello \e[2Kworld")).to eq('Hello world')
+ expect(convert_html("Hello \e[2Kworld")).to eq('<span class="">Hello world</span>')
end
it "prints simply red" do
@@ -32,7 +32,7 @@ describe Gitlab::Ci::Ansi2html do
end
it "resets colors after red on blue" do
- expect(convert_html("\e[31;44mHello\e[0m world")).to eq('<span class="term-fg-red term-bg-blue">Hello</span> world')
+ expect(convert_html("\e[31;44mHello\e[0m world")).to eq('<span class="term-fg-red term-bg-blue">Hello</span><span class=""> world</span>')
end
it "performs color change from red/blue to yellow/blue" do
@@ -44,11 +44,11 @@ describe Gitlab::Ci::Ansi2html do
end
it "performs color change from red/blue to reset to yellow/green" do
- expect(convert_html("\e[31;44mHello\e[0m \e[33;42mworld")).to eq('<span class="term-fg-red term-bg-blue">Hello</span> <span class="term-fg-yellow term-bg-green">world</span>')
+ expect(convert_html("\e[31;44mHello\e[0m \e[33;42mworld")).to eq('<span class="term-fg-red term-bg-blue">Hello</span><span class=""> </span><span class="term-fg-yellow term-bg-green">world</span>')
end
it "ignores unsupported codes" do
- expect(convert_html("\e[51mHello\e[0m")).to eq('Hello')
+ expect(convert_html("\e[51mHello\e[0m")).to eq('<span class="">Hello</span>')
end
it "prints light red" do
@@ -72,8 +72,8 @@ describe Gitlab::Ci::Ansi2html do
end
it "resets bold text" do
- expect(convert_html("\e[1mHello\e[21m world")).to eq('<span class="term-bold">Hello</span> world')
- expect(convert_html("\e[1mHello\e[22m world")).to eq('<span class="term-bold">Hello</span> world')
+ expect(convert_html("\e[1mHello\e[21m world")).to eq('<span class="term-bold">Hello</span><span class=""> world</span>')
+ expect(convert_html("\e[1mHello\e[22m world")).to eq('<span class="term-bold">Hello</span><span class=""> world</span>')
end
it "prints italic text" do
@@ -81,7 +81,7 @@ describe Gitlab::Ci::Ansi2html do
end
it "resets italic text" do
- expect(convert_html("\e[3mHello\e[23m world")).to eq('<span class="term-italic">Hello</span> world')
+ expect(convert_html("\e[3mHello\e[23m world")).to eq('<span class="term-italic">Hello</span><span class=""> world</span>')
end
it "prints underlined text" do
@@ -89,7 +89,7 @@ describe Gitlab::Ci::Ansi2html do
end
it "resets underlined text" do
- expect(convert_html("\e[4mHello\e[24m world")).to eq('<span class="term-underline">Hello</span> world')
+ expect(convert_html("\e[4mHello\e[24m world")).to eq('<span class="term-underline">Hello</span><span class=""> world</span>')
end
it "prints concealed text" do
@@ -97,7 +97,7 @@ describe Gitlab::Ci::Ansi2html do
end
it "resets concealed text" do
- expect(convert_html("\e[8mHello\e[28m world")).to eq('<span class="term-conceal">Hello</span> world')
+ expect(convert_html("\e[8mHello\e[28m world")).to eq('<span class="term-conceal">Hello</span><span class=""> world</span>')
end
it "prints crossed-out text" do
@@ -105,7 +105,7 @@ describe Gitlab::Ci::Ansi2html do
end
it "resets crossed-out text" do
- expect(convert_html("\e[9mHello\e[29m world")).to eq('<span class="term-cross">Hello</span> world')
+ expect(convert_html("\e[9mHello\e[29m world")).to eq('<span class="term-cross">Hello</span><span class=""> world</span>')
end
it "can print 256 xterm fg colors" do
@@ -137,15 +137,15 @@ describe Gitlab::Ci::Ansi2html do
end
it "prints &lt;" do
- expect(convert_html("<")).to eq('&lt;')
+ expect(convert_html("<")).to eq('<span class="">&lt;</span>')
end
it "replaces newlines with line break tags" do
- expect(convert_html("\n")).to eq('<br>')
+ expect(convert_html("\n")).to eq('<span class=""><br/><span class=""></span></span>')
end
it "groups carriage returns with newlines" do
- expect(convert_html("\r\n")).to eq('<br>')
+ expect(convert_html("\r\n")).to eq('<span class=""><br/><span class=""></span></span>')
end
describe "incremental update" do
@@ -166,14 +166,14 @@ describe Gitlab::Ci::Ansi2html do
let(:pre_text) { "\e[1mHello" }
let(:pre_html) { "<span class=\"term-bold\">Hello</span>" }
let(:text) { "\e[1mWorld" }
- let(:html) { "<span class=\"term-bold\"></span><span class=\"term-bold\">World</span>" }
+ let(:html) { "<span class=\"term-bold\">World</span>" }
it_behaves_like 'stateable converter'
end
context "with split sequence" do
let(:pre_text) { "\e[1m" }
- let(:pre_html) { "<span class=\"term-bold\"></span>" }
+ let(:pre_html) { "" }
let(:text) { "Hello" }
let(:html) { "<span class=\"term-bold\">Hello</span>" }
@@ -182,7 +182,7 @@ describe Gitlab::Ci::Ansi2html do
context "with partial sequence" do
let(:pre_text) { "Hello\e" }
- let(:pre_html) { "Hello" }
+ let(:pre_html) { "<span class=\"\">Hello</span>" }
let(:text) { "[1m World" }
let(:html) { "<span class=\"term-bold\"> World</span>" }
@@ -191,9 +191,9 @@ describe Gitlab::Ci::Ansi2html do
context 'with new line' do
let(:pre_text) { "Hello\r" }
- let(:pre_html) { "Hello\r" }
+ let(:pre_html) { "<span class=\"\">Hello\r</span>" }
let(:text) { "\nWorld" }
- let(:html) { "<br>World" }
+ let(:html) { "<span class=\"\"><br/><span class=\"\">World</span></span>" }
it_behaves_like 'stateable converter'
end
@@ -207,20 +207,20 @@ describe Gitlab::Ci::Ansi2html do
let(:section_start) { "section_start:#{section_start_time.to_i}:#{section_name}\r\033[0K"}
let(:section_end) { "section_end:#{section_end_time.to_i}:#{section_name}\r\033[0K"}
let(:section_start_html) do
- '<div class="hidden" data-action="start"'\
- " data-timestamp=\"#{section_start_time.to_i}\" data-section=\"#{section_name}\">"\
- "#{section_start[0...-5]}</div>"
+ '<div class="js-section-start fa fa-caret-down append-right-8 cursor-pointer"' \
+ " data-timestamp=\"#{section_start_time.to_i}\" data-section=\"#{class_name(section_name)}\"" \
+ ' role="button"></div>'
end
let(:section_end_html) do
- '<div class="hidden" data-action="end"'\
- " data-timestamp=\"#{section_end_time.to_i}\" data-section=\"#{section_name}\">"\
- "#{section_end[0...-5]}</div>"
+ "<div class=\"section-end\" data-section=\"#{class_name(section_name)}\"></div>"
end
shared_examples 'forbidden char in section_name' do
it 'ignores sections' do
text = "#{section_start}Some text#{section_end}"
- html = text.gsub("\033[0K", '').gsub('<', '&lt;')
+ class_name_start = section_start.gsub("\033[0K", '').gsub('<', '&lt;')
+ class_name_end = section_end.gsub("\033[0K", '').gsub('<', '&lt;')
+ html = %{<span class="">#{class_name_start}Some text#{class_name_end}</span>}
expect(convert_html(text)).to eq(html)
end
@@ -231,7 +231,11 @@ describe Gitlab::Ci::Ansi2html do
it 'prints light red' do
text = "#{section_start}\e[91mHello\e[0m\n#{section_end}"
- html = %{#{section_start_html}<span class="term-fg-l-red">Hello</span><br>#{section_end_html}}
+ header = %{<span class="term-fg-l-red section js-section-header js-s-#{class_name(section_name)}">Hello</span>}
+ line_break = %{<span class="section js-section-header js-s-#{class_name(section_name)}"><br/></span>}
+ line = %{<span class="section line s_#{class_name(section_name)}"></span>}
+ empty_line = %{<span class="section js-s-#{class_name(section_name)}"></span>}
+ html = "#{section_start_html}#{header}#{line_break}#{line}#{empty_line}#{section_end_html}"
expect(convert_html(text)).to eq(html)
end
@@ -294,4 +298,8 @@ describe Gitlab::Ci::Ansi2html do
stream = StringIO.new(data)
subject.convert(stream).html
end
+
+ def class_name(section)
+ subject::Converter.new.section_to_class_name(section)
+ end
end
diff --git a/spec/lib/gitlab/ci/build/policy/kubernetes_spec.rb b/spec/lib/gitlab/ci/build/policy/kubernetes_spec.rb
index 4884d5f8ba4..4510b82ca9d 100644
--- a/spec/lib/gitlab/ci/build/policy/kubernetes_spec.rb
+++ b/spec/lib/gitlab/ci/build/policy/kubernetes_spec.rb
@@ -4,24 +4,14 @@ describe Gitlab::Ci::Build::Policy::Kubernetes do
let(:pipeline) { create(:ci_pipeline, project: project) }
context 'when kubernetes service is active' do
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
- it 'is satisfied by a kubernetes pipeline' do
- expect(described_class.new('active'))
- .to be_satisfied_by(pipeline)
- end
- end
-
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
context 'when user configured kubernetes from CI/CD > Clusters' do
let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:project) { cluster.project }
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
+ it 'is satisfied by a kubernetes pipeline' do
+ expect(described_class.new('active'))
+ .to be_satisfied_by(pipeline)
+ end
end
end
diff --git a/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb b/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
index 5387863bd07..5ac5122e800 100644
--- a/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
+++ b/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
@@ -35,9 +35,15 @@ describe Gitlab::Ci::Build::Prerequisite::KubernetesNamespace do
end
context 'and a namespace is already created for this project' do
- let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, cluster: cluster, project: build.project) }
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token, cluster: cluster, project: build.project) }
it { is_expected.to be_falsey }
+
+ context 'and the service_account_token is blank' do
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :without_token, cluster: cluster, project: build.project) }
+
+ it { is_expected.to be_truthy }
+ end
end
context 'and cluster is project type' do
diff --git a/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb
index 3debd42ac65..50cb45c39d1 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Gitlab::Ci::Pipeline::Chain::Build do
set(:project) { create(:project, :repository) }
- set(:user) { create(:user) }
+ set(:user) { create(:user, developer_projects: [project]) }
let(:pipeline) { Ci::Pipeline.new }
let(:variables_attributes) do
diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexeme/matches_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexeme/matches_spec.rb
index 97da66d2bcc..a6fdec832a3 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/lexeme/matches_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/lexeme/matches_spec.rb
@@ -50,21 +50,21 @@ describe Gitlab::Ci::Pipeline::Expression::Lexeme::Matches do
let(:left_value) { 'my-string' }
let(:right_value) { Gitlab::UntrustedRegexp.new('something') }
- it { is_expected.to eq(nil) }
+ it { is_expected.to eq(false) }
end
context 'when left and right match' do
let(:left_value) { 'my-awesome-string' }
let(:right_value) { Gitlab::UntrustedRegexp.new('awesome.string$') }
- it { is_expected.to eq(3) }
+ it { is_expected.to eq(true) }
end
context 'when left is nil' do
let(:left_value) { nil }
let(:right_value) { Gitlab::UntrustedRegexp.new('pattern') }
- it { is_expected.to eq(nil) }
+ it { is_expected.to eq(false) }
end
context 'when left is a multiline string and matches right' do
@@ -78,7 +78,7 @@ describe Gitlab::Ci::Pipeline::Expression::Lexeme::Matches do
let(:right_value) { Gitlab::UntrustedRegexp.new('text-string') }
- it { is_expected.to eq(24) }
+ it { is_expected.to eq(true) }
end
context 'when left is a multiline string and does not match right' do
@@ -92,7 +92,7 @@ describe Gitlab::Ci::Pipeline::Expression::Lexeme::Matches do
let(:right_value) { Gitlab::UntrustedRegexp.new('text-string') }
- it { is_expected.to eq(nil) }
+ it { is_expected.to eq(false) }
end
context 'when a matching pattern uses regex flags' do
@@ -104,7 +104,7 @@ describe Gitlab::Ci::Pipeline::Expression::Lexeme::Matches do
let(:right_value) { Gitlab::UntrustedRegexp.new('(?i)awesome') }
- it { is_expected.to eq(3) }
+ it { is_expected.to eq(true) }
end
context 'when a non-matching pattern uses regex flags' do
@@ -116,7 +116,7 @@ describe Gitlab::Ci::Pipeline::Expression::Lexeme::Matches do
let(:right_value) { Gitlab::UntrustedRegexp.new('(?i)terrible') }
- it { is_expected.to eq(nil) }
+ it { is_expected.to eq(false) }
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb
index 057e2f3fbe8..a2c2e3653d5 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb
@@ -41,17 +41,17 @@ describe Gitlab::Ci::Pipeline::Expression::Statement do
'null == $UNDEFINED_VARIABLE' | true
'$PRESENT_VARIABLE' | 'my variable'
'$UNDEFINED_VARIABLE' | nil
- "$PRESENT_VARIABLE =~ /var.*e$/" | 3
- '$PRESENT_VARIABLE =~ /va\r.*e$/' | nil
- '$PRESENT_VARIABLE =~ /va\/r.*e$/' | nil
- "$PRESENT_VARIABLE =~ /var.*e$/" | 3
- "$PRESENT_VARIABLE =~ /^var.*/" | nil
- "$EMPTY_VARIABLE =~ /var.*/" | nil
- "$UNDEFINED_VARIABLE =~ /var.*/" | nil
- "$PRESENT_VARIABLE =~ /VAR.*/i" | 3
- '$PATH_VARIABLE =~ /path\/variable/' | 2
- '$FULL_PATH_VARIABLE =~ /^\/a\/full\/path\/variable\/value$/' | 0
- '$FULL_PATH_VARIABLE =~ /\\/path\\/variable\\/value$/' | 7
+ "$PRESENT_VARIABLE =~ /var.*e$/" | true
+ '$PRESENT_VARIABLE =~ /va\r.*e$/' | false
+ '$PRESENT_VARIABLE =~ /va\/r.*e$/' | false
+ "$PRESENT_VARIABLE =~ /var.*e$/" | true
+ "$PRESENT_VARIABLE =~ /^var.*/" | false
+ "$EMPTY_VARIABLE =~ /var.*/" | false
+ "$UNDEFINED_VARIABLE =~ /var.*/" | false
+ "$PRESENT_VARIABLE =~ /VAR.*/i" | true
+ '$PATH_VARIABLE =~ /path\/variable/' | true
+ '$FULL_PATH_VARIABLE =~ /^\/a\/full\/path\/variable\/value$/' | true
+ '$FULL_PATH_VARIABLE =~ /\\/path\\/variable\\/value$/' | true
'$PRESENT_VARIABLE != "my variable"' | false
'"my variable" != $PRESENT_VARIABLE' | false
'$PRESENT_VARIABLE != null' | true
@@ -82,7 +82,7 @@ describe Gitlab::Ci::Pipeline::Expression::Statement do
'"string" && "string"' | 'string'
'null && null' | nil
- '$PRESENT_VARIABLE =~ /my var/ && $EMPTY_VARIABLE =~ /nope/' | nil
+ '$PRESENT_VARIABLE =~ /my var/ && $EMPTY_VARIABLE =~ /nope/' | false
'$EMPTY_VARIABLE == "" && $PRESENT_VARIABLE' | 'my variable'
'$EMPTY_VARIABLE == "" && $PRESENT_VARIABLE != "nope"' | true
'$PRESENT_VARIABLE && $EMPTY_VARIABLE' | ''
@@ -90,17 +90,17 @@ describe Gitlab::Ci::Pipeline::Expression::Statement do
'$UNDEFINED_VARIABLE && $EMPTY_VARIABLE' | nil
'$UNDEFINED_VARIABLE && $PRESENT_VARIABLE' | nil
- '$FULL_PATH_VARIABLE =~ /^\/a\/full\/path\/variable\/value$/ && $PATH_VARIABLE =~ /path\/variable/' | 2
- '$FULL_PATH_VARIABLE =~ /^\/a\/bad\/path\/variable\/value$/ && $PATH_VARIABLE =~ /path\/variable/' | nil
- '$FULL_PATH_VARIABLE =~ /^\/a\/full\/path\/variable\/value$/ && $PATH_VARIABLE =~ /bad\/path\/variable/' | nil
- '$FULL_PATH_VARIABLE =~ /^\/a\/bad\/path\/variable\/value$/ && $PATH_VARIABLE =~ /bad\/path\/variable/' | nil
+ '$FULL_PATH_VARIABLE =~ /^\/a\/full\/path\/variable\/value$/ && $PATH_VARIABLE =~ /path\/variable/' | true
+ '$FULL_PATH_VARIABLE =~ /^\/a\/bad\/path\/variable\/value$/ && $PATH_VARIABLE =~ /path\/variable/' | false
+ '$FULL_PATH_VARIABLE =~ /^\/a\/full\/path\/variable\/value$/ && $PATH_VARIABLE =~ /bad\/path\/variable/' | false
+ '$FULL_PATH_VARIABLE =~ /^\/a\/bad\/path\/variable\/value$/ && $PATH_VARIABLE =~ /bad\/path\/variable/' | false
- '$FULL_PATH_VARIABLE =~ /^\/a\/full\/path\/variable\/value$/ || $PATH_VARIABLE =~ /path\/variable/' | 0
- '$FULL_PATH_VARIABLE =~ /^\/a\/bad\/path\/variable\/value$/ || $PATH_VARIABLE =~ /path\/variable/' | 2
- '$FULL_PATH_VARIABLE =~ /^\/a\/full\/path\/variable\/value$/ || $PATH_VARIABLE =~ /bad\/path\/variable/' | 0
- '$FULL_PATH_VARIABLE =~ /^\/a\/bad\/path\/variable\/value$/ || $PATH_VARIABLE =~ /bad\/path\/variable/' | nil
+ '$FULL_PATH_VARIABLE =~ /^\/a\/full\/path\/variable\/value$/ || $PATH_VARIABLE =~ /path\/variable/' | true
+ '$FULL_PATH_VARIABLE =~ /^\/a\/bad\/path\/variable\/value$/ || $PATH_VARIABLE =~ /path\/variable/' | true
+ '$FULL_PATH_VARIABLE =~ /^\/a\/full\/path\/variable\/value$/ || $PATH_VARIABLE =~ /bad\/path\/variable/' | true
+ '$FULL_PATH_VARIABLE =~ /^\/a\/bad\/path\/variable\/value$/ || $PATH_VARIABLE =~ /bad\/path\/variable/' | false
- '$PRESENT_VARIABLE =~ /my var/ || $EMPTY_VARIABLE =~ /nope/' | 0
+ '$PRESENT_VARIABLE =~ /my var/ || $EMPTY_VARIABLE =~ /nope/' | true
'$EMPTY_VARIABLE == "" || $PRESENT_VARIABLE' | true
'$PRESENT_VARIABLE != "nope" || $EMPTY_VARIABLE == ""' | true
@@ -117,21 +117,6 @@ describe Gitlab::Ci::Pipeline::Expression::Statement do
it "evaluates to `#{params[:value].inspect}`" do
expect(subject.evaluate).to eq(value)
end
-
- # This test is used to ensure that our parser
- # returns exactly the same results as if we
- # were evaluating using ruby's `eval`
- context 'when using Ruby eval' do
- let(:expression_ruby) do
- expression
- .gsub(/null/, 'nil')
- .gsub(/\$([a-zA-Z_][a-zA-Z0-9_]*)/) { "variables['#{Regexp.last_match(1)}']" }
- end
-
- it 'behaves exactly the same' do
- expect(instance_eval(expression_ruby)).to eq(subject.evaluate)
- end
- end
end
context 'with the ci_variables_complex_expressions feature flag disabled' do
diff --git a/spec/lib/gitlab/ci/trace/stream_spec.rb b/spec/lib/gitlab/ci/trace/stream_spec.rb
index e45ea1c2528..35250632e86 100644
--- a/spec/lib/gitlab/ci/trace/stream_spec.rb
+++ b/spec/lib/gitlab/ci/trace/stream_spec.rb
@@ -64,7 +64,10 @@ describe Gitlab::Ci::Trace::Stream, :clean_gitlab_redis_cache do
result = stream.html
- expect(result).to eq("ヾ(´༎ຶД༎ຶ`)ノ<br><span class=\"term-fg-green\">許功蓋</span><br>")
+ expect(result).to eq(
+ "<span class=\"\">ヾ(´༎ຶД༎ຶ`)ノ<br/><span class=\"\"></span></span>"\
+ "<span class=\"term-fg-green\">許功蓋</span><span class=\"\"><br/>"\
+ "<span class=\"\"></span></span>")
expect(result.encoding).to eq(Encoding.default_external)
end
end
@@ -250,7 +253,7 @@ describe Gitlab::Ci::Trace::Stream, :clean_gitlab_redis_cache do
it 'returns html content with state' do
result = stream.html_with_state
- expect(result.html).to eq("1234")
+ expect(result.html).to eq("<span class=\"\">1234</span>")
end
context 'follow-up state' do
@@ -266,7 +269,7 @@ describe Gitlab::Ci::Trace::Stream, :clean_gitlab_redis_cache do
result = stream.html_with_state(last_result.state)
expect(result.append).to be_truthy
- expect(result.html).to eq("5678")
+ expect(result.html).to eq("<span class=\"\">5678</span>")
end
end
end
@@ -302,11 +305,13 @@ describe Gitlab::Ci::Trace::Stream, :clean_gitlab_redis_cache do
describe '#html' do
shared_examples_for 'htmls' do
it "returns html" do
- expect(stream.html).to eq("12<br>34<br>56")
+ expect(stream.html).to eq(
+ "<span class=\"\">12<br/><span class=\"\">34<br/>"\
+ "<span class=\"\">56</span></span></span>")
end
it "returns html for last line only" do
- expect(stream.html(last_lines: 1)).to eq("56")
+ expect(stream.html(last_lines: 1)).to eq("<span class=\"\">56</span>")
end
end
diff --git a/spec/lib/gitlab/cycle_analytics/code_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/code_stage_spec.rb
index e8fc67acf05..c738cc49c1f 100644
--- a/spec/lib/gitlab/cycle_analytics/code_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/code_stage_spec.rb
@@ -4,5 +4,41 @@ require 'lib/gitlab/cycle_analytics/shared_stage_spec'
describe Gitlab::CycleAnalytics::CodeStage do
let(:stage_name) { :code }
+ let(:project) { create(:project) }
+ let!(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) }
+ let!(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
+ let!(:issue_3) { create(:issue, project: project, created_at: 60.minutes.ago) }
+ let!(:mr_1) { create(:merge_request, source_project: project, created_at: 15.minutes.ago) }
+ let!(:mr_2) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'A') }
+ let!(:mr_3) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'B') }
+ let(:stage) { described_class.new(project: project, options: { from: 2.days.ago, current_user: project.creator }) }
+
+ before do
+ issue_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago, first_mentioned_in_commit_at: 45.minutes.ago)
+ issue_2.metrics.update!(first_added_to_board_at: 60.minutes.ago, first_mentioned_in_commit_at: 40.minutes.ago)
+ issue_3.metrics.update!(first_added_to_board_at: 60.minutes.ago, first_mentioned_in_commit_at: 40.minutes.ago)
+ create(:merge_requests_closing_issues, merge_request: mr_1, issue: issue_1)
+ create(:merge_requests_closing_issues, merge_request: mr_2, issue: issue_2)
+ end
+
it_behaves_like 'base stage'
+
+ describe '#median' do
+ around do |example|
+ Timecop.freeze { example.run }
+ end
+
+ it 'counts median from issues with metrics' do
+ expect(stage.median).to eq(ISSUES_MEDIAN)
+ end
+ end
+
+ describe '#events' do
+ it 'exposes merge requests that closes issues' do
+ result = stage.events
+
+ expect(result.count).to eq(2)
+ expect(result.map { |event| event[:title] }).to contain_exactly(mr_1.title, mr_2.title)
+ end
+ end
end
diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb
index 397dd4e5d2c..f8b103c0fab 100644
--- a/spec/lib/gitlab/cycle_analytics/events_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb
@@ -53,20 +53,28 @@ describe 'cycle analytics events' do
describe '#plan_events' do
let(:stage) { :plan }
- it 'has a title' do
- expect(events.first[:title]).not_to be_nil
+ before do
+ create_commit_referencing_issue(context)
end
- it 'has a sha short ID' do
- expect(events.first[:short_sha]).not_to be_nil
+ it 'has the total time' do
+ expect(events.first[:total_time]).not_to be_empty
+ end
+
+ it 'has a title' do
+ expect(events.first[:title]).to eq(context.title)
end
it 'has the URL' do
- expect(events.first[:commit_url]).not_to be_nil
+ expect(events.first[:url]).not_to be_nil
end
- it 'has the total time' do
- expect(events.first[:total_time]).not_to be_empty
+ it 'has an iid' do
+ expect(events.first[:iid]).to eq(context.iid.to_s)
+ end
+
+ it 'has a created_at timestamp' do
+ expect(events.first[:created_at]).to end_with('ago')
end
it "has the author's URL" do
@@ -78,12 +86,13 @@ describe 'cycle analytics events' do
end
it "has the author's name" do
- expect(events.first[:author][:name]).not_to be_nil
+ expect(events.first[:author][:name]).to eq(context.author.name)
end
end
describe '#code_events' do
let(:stage) { :code }
+ let!(:merge_request) { MergeRequest.first }
before do
create_commit_referencing_issue(context)
@@ -122,6 +131,7 @@ describe 'cycle analytics events' do
let(:stage) { :test }
let(:merge_request) { MergeRequest.first }
+ let!(:context) { create(:issue, project: project, created_at: 2.days.ago) }
let!(:pipeline) do
create(:ci_pipeline,
@@ -137,6 +147,7 @@ describe 'cycle analytics events' do
pipeline.run!
pipeline.succeed!
+ merge_merge_requests_closing_issue(user, project, context)
end
it 'has the name' do
@@ -180,6 +191,10 @@ describe 'cycle analytics events' do
let(:stage) { :review }
let!(:context) { create(:issue, project: project, created_at: 2.days.ago) }
+ before do
+ merge_merge_requests_closing_issue(user, project, context)
+ end
+
it 'has the total time' do
expect(events.first[:total_time]).not_to be_empty
end
diff --git a/spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb
index 3127f01989d..3b6af9cbaed 100644
--- a/spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb
@@ -3,6 +3,37 @@ require 'lib/gitlab/cycle_analytics/shared_stage_spec'
describe Gitlab::CycleAnalytics::IssueStage do
let(:stage_name) { :issue }
+ let(:project) { create(:project) }
+ let!(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) }
+ let!(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
+ let!(:issue_3) { create(:issue, project: project, created_at: 30.minutes.ago) }
+ let!(:issue_without_milestone) { create(:issue, project: project, created_at: 1.minute.ago) }
+ let(:stage) { described_class.new(project: project, options: { from: 2.days.ago, current_user: project.creator }) }
+
+ before do
+ issue_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago )
+ issue_2.metrics.update!(first_added_to_board_at: 30.minutes.ago)
+ issue_3.metrics.update!(first_added_to_board_at: 15.minutes.ago)
+ end
it_behaves_like 'base stage'
+
+ describe '#median' do
+ around do |example|
+ Timecop.freeze { example.run }
+ end
+
+ it 'counts median from issues with metrics' do
+ expect(stage.median).to eq(ISSUES_MEDIAN)
+ end
+ end
+
+ describe '#events' do
+ it 'exposes issues with metrics' do
+ result = stage.events
+
+ expect(result.count).to eq(3)
+ expect(result.map { |event| event[:title] }).to contain_exactly(issue_1.title, issue_2.title, issue_3.title)
+ end
+ end
end
diff --git a/spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb
index 4c715921ad6..506a8160412 100644
--- a/spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb
@@ -3,6 +3,37 @@ require 'lib/gitlab/cycle_analytics/shared_stage_spec'
describe Gitlab::CycleAnalytics::PlanStage do
let(:stage_name) { :plan }
+ let(:project) { create(:project) }
+ let!(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) }
+ let!(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
+ let!(:issue_3) { create(:issue, project: project, created_at: 30.minutes.ago) }
+ let!(:issue_without_milestone) { create(:issue, project: project, created_at: 1.minute.ago) }
+ let(:stage) { described_class.new(project: project, options: { from: 2.days.ago, current_user: project.creator }) }
+
+ before do
+ issue_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago, first_mentioned_in_commit_at: 10.minutes.ago)
+ issue_2.metrics.update!(first_added_to_board_at: 30.minutes.ago, first_mentioned_in_commit_at: 20.minutes.ago)
+ issue_3.metrics.update!(first_added_to_board_at: 15.minutes.ago)
+ end
it_behaves_like 'base stage'
+
+ describe '#median' do
+ around do |example|
+ Timecop.freeze { example.run }
+ end
+
+ it 'counts median from issues with metrics' do
+ expect(stage.median).to eq(ISSUES_MEDIAN)
+ end
+ end
+
+ describe '#events' do
+ it 'exposes issues with metrics' do
+ result = stage.events
+
+ expect(result.count).to eq(2)
+ expect(result.map { |event| event[:title] }).to contain_exactly(issue_1.title, issue_2.title)
+ end
+ end
end
diff --git a/spec/lib/gitlab/cycle_analytics/review_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/review_stage_spec.rb
index 1412c8dfa08..f072a9644e8 100644
--- a/spec/lib/gitlab/cycle_analytics/review_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/review_stage_spec.rb
@@ -3,6 +3,43 @@ require 'lib/gitlab/cycle_analytics/shared_stage_spec'
describe Gitlab::CycleAnalytics::ReviewStage do
let(:stage_name) { :review }
+ let(:project) { create(:project) }
+ let!(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) }
+ let!(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
+ let!(:issue_3) { create(:issue, project: project, created_at: 60.minutes.ago) }
+ let!(:mr_1) { create(:merge_request, :closed, source_project: project, created_at: 60.minutes.ago) }
+ let!(:mr_2) { create(:merge_request, :closed, source_project: project, created_at: 40.minutes.ago, source_branch: 'A') }
+ let!(:mr_3) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'B') }
+ let!(:mr_4) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'C') }
+ let(:stage) { described_class.new(project: project, options: { from: 2.days.ago, current_user: project.creator }) }
+
+ before do
+ mr_1.metrics.update!(merged_at: 30.minutes.ago)
+ mr_2.metrics.update!(merged_at: 10.minutes.ago)
+
+ create(:merge_requests_closing_issues, merge_request: mr_1, issue: issue_1)
+ create(:merge_requests_closing_issues, merge_request: mr_2, issue: issue_2)
+ create(:merge_requests_closing_issues, merge_request: mr_3, issue: issue_3)
+ end
it_behaves_like 'base stage'
+
+ describe '#median' do
+ around do |example|
+ Timecop.freeze { example.run }
+ end
+
+ it 'counts median from issues with metrics' do
+ expect(stage.median).to eq(ISSUES_MEDIAN)
+ end
+ end
+
+ describe '#events' do
+ it 'exposes merge requests that close issues' do
+ result = stage.events
+
+ expect(result.count).to eq(2)
+ expect(result.map { |event| event[:title] }).to contain_exactly(mr_1.title, mr_2.title)
+ end
+ end
end
diff --git a/spec/lib/gitlab/cycle_analytics/shared_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/shared_stage_spec.rb
index 08425acbfc8..1a4b572cc11 100644
--- a/spec/lib/gitlab/cycle_analytics/shared_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/shared_stage_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
shared_examples 'base stage' do
+ ISSUES_MEDIAN = 30.minutes.to_i
+
let(:stage) { described_class.new(project: double, options: {}) }
before do
diff --git a/spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb
index 8154b3ac701..17d5fbb9733 100644
--- a/spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb
@@ -4,5 +4,46 @@ require 'lib/gitlab/cycle_analytics/shared_stage_spec'
describe Gitlab::CycleAnalytics::StagingStage do
let(:stage_name) { :staging }
+ let(:project) { create(:project) }
+ let!(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) }
+ let!(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
+ let!(:issue_3) { create(:issue, project: project, created_at: 60.minutes.ago) }
+ let!(:mr_1) { create(:merge_request, :closed, source_project: project, created_at: 60.minutes.ago) }
+ let!(:mr_2) { create(:merge_request, :closed, source_project: project, created_at: 40.minutes.ago, source_branch: 'A') }
+ let!(:mr_3) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'B') }
+ let(:build_1) { create(:ci_build, project: project) }
+ let(:build_2) { create(:ci_build, project: project) }
+
+ let(:stage) { described_class.new(project: project, options: { from: 2.days.ago, current_user: project.creator }) }
+
+ before do
+ mr_1.metrics.update!(merged_at: 80.minutes.ago, first_deployed_to_production_at: 50.minutes.ago, pipeline_id: build_1.commit_id)
+ mr_2.metrics.update!(merged_at: 60.minutes.ago, first_deployed_to_production_at: 30.minutes.ago, pipeline_id: build_2.commit_id)
+ mr_3.metrics.update!(merged_at: 10.minutes.ago, first_deployed_to_production_at: 3.days.ago, pipeline_id: create(:ci_build, project: project).commit_id)
+
+ create(:merge_requests_closing_issues, merge_request: mr_1, issue: issue_1)
+ create(:merge_requests_closing_issues, merge_request: mr_2, issue: issue_2)
+ create(:merge_requests_closing_issues, merge_request: mr_3, issue: issue_3)
+ end
+
it_behaves_like 'base stage'
+
+ describe '#median' do
+ around do |example|
+ Timecop.freeze { example.run }
+ end
+
+ it 'counts median from issues with metrics' do
+ expect(stage.median).to eq(ISSUES_MEDIAN)
+ end
+ end
+
+ describe '#events' do
+ it 'exposes builds connected to merge request' do
+ result = stage.events
+
+ expect(result.count).to eq(2)
+ expect(result.map { |event| event[:name] }).to contain_exactly(build_1.name, build_2.name)
+ end
+ end
end
diff --git a/spec/lib/gitlab/gpg/commit_spec.rb b/spec/lib/gitlab/gpg/commit_spec.rb
index 8229f0eb794..47e6f5d4220 100644
--- a/spec/lib/gitlab/gpg/commit_spec.rb
+++ b/spec/lib/gitlab/gpg/commit_spec.rb
@@ -109,6 +109,89 @@ describe Gitlab::Gpg::Commit do
end
end
+ context 'valid key signed using recent version of Gnupg' do
+ let!(:commit) { create :commit, project: project, sha: commit_sha, committer_email: GpgHelpers::User1.emails.first }
+
+ let!(:user) { create(:user, email: GpgHelpers::User1.emails.first) }
+
+ let!(:gpg_key) do
+ create :gpg_key, key: GpgHelpers::User1.public_key, user: user
+ end
+
+ let!(:crypto) { instance_double(GPGME::Crypto) }
+
+ before do
+ fake_signature = [
+ GpgHelpers::User1.signed_commit_signature,
+ GpgHelpers::User1.signed_commit_base_data
+ ]
+
+ allow(Gitlab::Git::Commit).to receive(:extract_signature_lazily)
+ .with(Gitlab::Git::Repository, commit_sha)
+ .and_return(fake_signature)
+ end
+
+ it 'returns a valid signature' do
+ verified_signature = double('verified-signature', fingerprint: GpgHelpers::User1.fingerprint, valid?: true)
+ allow(GPGME::Crypto).to receive(:new).and_return(crypto)
+ allow(crypto).to receive(:verify).and_return(verified_signature)
+
+ signature = described_class.new(commit).signature
+
+ expect(signature).to have_attributes(
+ commit_sha: commit_sha,
+ project: project,
+ gpg_key: gpg_key,
+ gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
+ gpg_key_user_name: GpgHelpers::User1.names.first,
+ gpg_key_user_email: GpgHelpers::User1.emails.first,
+ verification_status: 'verified'
+ )
+ end
+ end
+
+ context 'valid key signed using older version of Gnupg' do
+ let!(:commit) { create :commit, project: project, sha: commit_sha, committer_email: GpgHelpers::User1.emails.first }
+
+ let!(:user) { create(:user, email: GpgHelpers::User1.emails.first) }
+
+ let!(:gpg_key) do
+ create :gpg_key, key: GpgHelpers::User1.public_key, user: user
+ end
+
+ let!(:crypto) { instance_double(GPGME::Crypto) }
+
+ before do
+ fake_signature = [
+ GpgHelpers::User1.signed_commit_signature,
+ GpgHelpers::User1.signed_commit_base_data
+ ]
+
+ allow(Gitlab::Git::Commit).to receive(:extract_signature_lazily)
+ .with(Gitlab::Git::Repository, commit_sha)
+ .and_return(fake_signature)
+ end
+
+ it 'returns a valid signature' do
+ keyid = GpgHelpers::User1.fingerprint.last(16)
+ verified_signature = double('verified-signature', fingerprint: keyid, valid?: true)
+ allow(GPGME::Crypto).to receive(:new).and_return(crypto)
+ allow(crypto).to receive(:verify).and_return(verified_signature)
+
+ signature = described_class.new(commit).signature
+
+ expect(signature).to have_attributes(
+ commit_sha: commit_sha,
+ project: project,
+ gpg_key: gpg_key,
+ gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
+ gpg_key_user_name: GpgHelpers::User1.names.first,
+ gpg_key_user_email: GpgHelpers::User1.emails.first,
+ verification_status: 'verified'
+ )
+ end
+ end
+
context 'commit signed with a subkey' do
let!(:commit) { create :commit, project: project, sha: commit_sha, committer_email: GpgHelpers::User3.emails.first }
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 41ef60dc6f8..7a250603b6b 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -203,6 +203,8 @@ deploy_keys:
services:
- project
- service_hook
+- jira_tracker_data
+- issue_tracker_data
hooks:
- project
- web_hook_logs
diff --git a/spec/migrations/migrate_k8s_service_integration_spec.rb b/spec/migrations/migrate_k8s_service_integration_spec.rb
new file mode 100644
index 00000000000..4dd0c09632a
--- /dev/null
+++ b/spec/migrations/migrate_k8s_service_integration_spec.rb
@@ -0,0 +1,161 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20190517153211_migrate_k8s_service_integration.rb')
+
+describe MigrateK8sServiceIntegration, :migration do
+ context 'template service' do
+ context 'with namespace' do
+ let!(:service) do
+ MigrateK8sServiceIntegration::Service.create!(
+ active: true,
+ template: true,
+ category: 'deployment',
+ type: 'KubernetesService',
+ properties: "{\"namespace\":\"prod\",\"api_url\":\"https://sample.kubernetes.com\",\"ca_pem\":\"ca_pem-sample\",\"token\":\"token-sample\"}"
+ )
+ end
+
+ let(:cluster) { MigrateK8sServiceIntegration::Cluster.instance_type.last! }
+ let(:platform) { cluster.platform_kubernetes }
+
+ it 'migrates the KubernetesService template to Platform::Kubernetes' do
+ expect { migrate! }.to change { MigrateK8sServiceIntegration::Cluster.count }.by(1)
+
+ expect(cluster).to be_enabled
+ expect(cluster).to be_user
+ expect(cluster).not_to be_managed
+ expect(cluster.environment_scope).to eq('*')
+ expect(platform.api_url).to eq('https://sample.kubernetes.com')
+ expect(platform.ca_cert).to eq('ca_pem-sample')
+ expect(platform.namespace).to eq('prod')
+ expect(platform.token).to eq('token-sample')
+ end
+ end
+
+ context 'without namespace' do
+ let!(:service) do
+ MigrateK8sServiceIntegration::Service.create!(
+ active: true,
+ template: true,
+ category: 'deployment',
+ type: 'KubernetesService',
+ properties: "{\"namespace\":\"\",\"api_url\":\"https://sample.kubernetes.com\",\"ca_pem\":\"ca_pem-sample\",\"token\":\"token-sample\"}"
+ )
+ end
+
+ let(:cluster) { MigrateK8sServiceIntegration::Cluster.instance_type.last! }
+ let(:platform) { cluster.platform_kubernetes }
+
+ it 'migrates the KubernetesService template to Platform::Kubernetes' do
+ expect { migrate! }.to change { MigrateK8sServiceIntegration::Cluster.count }.by(1)
+
+ expect(cluster).to be_enabled
+ expect(cluster).to be_user
+ expect(cluster).not_to be_managed
+ expect(cluster.environment_scope).to eq('*')
+ expect(platform.api_url).to eq('https://sample.kubernetes.com')
+ expect(platform.ca_cert).to eq('ca_pem-sample')
+ expect(platform.namespace).to be_nil
+ expect(platform.token).to eq('token-sample')
+ end
+ end
+
+ context 'with nullified parameters' do
+ let!(:service) do
+ MigrateK8sServiceIntegration::Service.create!(
+ active: true,
+ template: true,
+ category: 'deployment',
+ type: 'KubernetesService',
+ properties: "{}"
+ )
+ end
+
+ it 'does not migrate the KubernetesService' do
+ expect { migrate! }.not_to change { MigrateK8sServiceIntegration::Cluster.count }
+ end
+ end
+
+ context 'when disabled' do
+ let!(:service) do
+ MigrateK8sServiceIntegration::Service.create!(
+ active: false,
+ template: true,
+ category: 'deployment',
+ type: 'KubernetesService',
+ properties: "{\"namespace\":\"prod\",\"api_url\":\"https://sample.kubernetes.com\",\"ca_pem\":\"ca_pem-sample\",\"token\":\"token-sample\"}"
+ )
+ end
+
+ let(:cluster) { MigrateK8sServiceIntegration::Cluster.instance_type.last! }
+ let(:platform) { cluster.platform_kubernetes }
+
+ it 'migrates the KubernetesService template to Platform::Kubernetes' do
+ expect { migrate! }.to change { MigrateK8sServiceIntegration::Cluster.count }.by(1)
+
+ expect(cluster).not_to be_enabled
+ expect(cluster).to be_user
+ expect(cluster).not_to be_managed
+ expect(cluster.environment_scope).to eq('*')
+ expect(platform.api_url).to eq('https://sample.kubernetes.com')
+ expect(platform.ca_cert).to eq('ca_pem-sample')
+ expect(platform.namespace).to eq('prod')
+ expect(platform.token).to eq('token-sample')
+ end
+ end
+
+ context 'when an instance cluster already exists' do
+ let!(:service) do
+ MigrateK8sServiceIntegration::Service.create!(
+ active: true,
+ template: true,
+ category: 'deployment',
+ type: 'KubernetesService',
+ properties: "{\"namespace\":\"prod\",\"api_url\":\"https://sample.kubernetes.com\",\"ca_pem\":\"ca_pem-sample\",\"token\":\"token-sample\"}"
+ )
+ end
+
+ let!(:existing_cluster) do
+ MigrateK8sServiceIntegration::Cluster.create!(
+ name: 'test-cluster',
+ cluster_type: :instance_type,
+ managed: true,
+ provider_type: :user,
+ platform_type: :kubernetes
+ )
+ end
+ let(:new_cluster) { MigrateK8sServiceIntegration::Cluster.instance_type.last! }
+ let(:platform) { new_cluster.platform_kubernetes }
+
+ it 'migrates the KubernetesService template to disabled Platform::Kubernetes' do
+ expect { migrate! }.to change { MigrateK8sServiceIntegration::Cluster.count }.by(1)
+
+ expect(new_cluster).not_to be_enabled
+ expect(new_cluster).to be_user
+ expect(new_cluster).not_to be_managed
+ expect(new_cluster.environment_scope).to eq('*')
+ expect(platform.api_url).to eq('https://sample.kubernetes.com')
+ expect(platform.ca_cert).to eq('ca_pem-sample')
+ expect(platform.namespace).to eq('prod')
+ expect(platform.token).to eq('token-sample')
+ end
+ end
+ end
+
+ context 'non-template service' do
+ let!(:service) do
+ MigrateK8sServiceIntegration::Service.create!(
+ active: true,
+ template: false,
+ category: 'deployment',
+ type: 'KubernetesService',
+ properties: "{\"namespace\":\"prod\",\"api_url\":\"https://sample.kubernetes.com\",\"ca_pem\":\"ca_pem-sample\",\"token\":\"token-sample\"}"
+ )
+ end
+
+ it 'does not migrate the KubernetesService' do
+ expect { migrate! }.not_to change { MigrateK8sServiceIntegration::Cluster.count }
+ end
+ end
+end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index a8701f0efa4..6ebc6337d50 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -962,7 +962,11 @@ describe Ci::Pipeline, :mailer do
end
context 'when kubernetes is active' do
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
+ context 'when user configured kubernetes from CI/CD > Clusters' do
+ let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.project }
+ let(:pipeline) { build(:ci_pipeline, project: project, config: config) }
+
it 'returns seeds for kubernetes dependent job' do
seeds = pipeline.stage_seeds
@@ -971,21 +975,6 @@ describe Ci::Pipeline, :mailer do
expect(seeds.dig(1, 0, :name)).to eq 'production'
end
end
-
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project) }
- let(:pipeline) { build(:ci_pipeline, project: project, config: config) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
- context 'when user configured kubernetes from CI/CD > Clusters' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:project) { cluster.project }
- let(:pipeline) { build(:ci_pipeline, project: project, config: config) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
end
context 'when kubernetes is not active' do
@@ -1679,23 +1668,13 @@ describe Ci::Pipeline, :mailer do
describe '#has_kubernetes_active?' do
context 'when kubernetes is active' do
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
- it 'returns true' do
- expect(pipeline).to have_kubernetes_active
- end
- end
-
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
context 'when user configured kubernetes from CI/CD > Clusters' do
let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:project) { cluster.project }
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
+ it 'returns true' do
+ expect(pipeline).to have_kubernetes_active
+ end
end
end
@@ -2736,7 +2715,7 @@ describe Ci::Pipeline, :mailer do
create(:ci_pipeline,
project: project,
sha: project.commit('master').sha,
- user: create(:user))
+ user: project.owner)
end
before do
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index f206bb41f45..52661178d76 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -514,19 +514,43 @@ describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
subject { cluster.allow_user_defined_namespace? }
context 'project type cluster' do
- it { is_expected.to be_truthy }
+ context 'gitlab managed' do
+ it { is_expected.to be_truthy }
+ end
+
+ context 'not managed' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, managed: false) }
+
+ it { is_expected.to be_truthy }
+ end
end
context 'group type cluster' do
- let(:cluster) { create(:cluster, :provided_by_gcp, :group) }
+ context 'gitlab managed' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :group) }
- it { is_expected.to be_falsey }
+ it { is_expected.to be_falsey }
+ end
+
+ context 'not managed' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :group, managed: false) }
+
+ it { is_expected.to be_truthy }
+ end
end
context 'instance type cluster' do
- let(:cluster) { create(:cluster, :provided_by_gcp, :instance) }
+ context 'gitlab managed' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :instance) }
- it { is_expected.to be_falsey }
+ it { is_expected.to be_falsey }
+ end
+
+ context 'not managed' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :instance, managed: false) }
+
+ it { is_expected.to be_truthy }
+ end
end
end
@@ -555,6 +579,63 @@ describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
end
end
+ describe '#find_or_initialize_kubernetes_namespace_for_project' do
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.projects.first }
+
+ subject { cluster.find_or_initialize_kubernetes_namespace_for_project(project) }
+
+ context 'kubernetes namespace exists' do
+ context 'with no service account token' do
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, project: project, cluster: cluster) }
+
+ it { is_expected.to eq kubernetes_namespace }
+ end
+
+ context 'with a service account token' do
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token, project: project, cluster: cluster) }
+
+ it { is_expected.to eq kubernetes_namespace }
+ end
+ end
+
+ context 'kubernetes namespace does not exist' do
+ it 'initializes a new namespace and sets default values' do
+ expect(subject).to be_new_record
+ expect(subject.project).to eq project
+ expect(subject.cluster).to eq cluster
+ expect(subject.namespace).to be_present
+ expect(subject.service_account_name).to be_present
+ end
+ end
+
+ context 'a custom scope is provided' do
+ let(:scope) { cluster.kubernetes_namespaces.has_service_account_token }
+
+ subject { cluster.find_or_initialize_kubernetes_namespace_for_project(project, scope: scope) }
+
+ context 'kubernetes namespace exists' do
+ context 'with no service account token' do
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, project: project, cluster: cluster) }
+
+ it 'initializes a new namespace and sets default values' do
+ expect(subject).to be_new_record
+ expect(subject.project).to eq project
+ expect(subject.cluster).to eq cluster
+ expect(subject.namespace).to be_present
+ expect(subject.service_account_name).to be_present
+ end
+ end
+
+ context 'with a service account token' do
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token, project: project, cluster: cluster) }
+
+ it { is_expected.to eq kubernetes_namespace }
+ end
+ end
+ end
+ end
+
describe '#predefined_variables' do
subject { cluster.predefined_variables }
diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb
index c485850c16e..1fb3a8de808 100644
--- a/spec/models/clusters/platforms/kubernetes_spec.rb
+++ b/spec/models/clusters/platforms/kubernetes_spec.rb
@@ -223,19 +223,33 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
let(:namespace) { 'namespace-123' }
it { is_expected.to eq(namespace) }
+
+ context 'kubernetes namespace is present but has no service account token' do
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, cluster: cluster) }
+
+ it { is_expected.to eq(namespace) }
+ end
end
context 'with no namespace assigned' do
let(:namespace) { nil }
context 'when kubernetes namespace is present' do
- let(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, cluster: cluster) }
+ let(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token, cluster: cluster) }
before do
kubernetes_namespace
end
it { is_expected.to eq(kubernetes_namespace.namespace) }
+
+ context 'kubernetes namespace has no service account token' do
+ before do
+ kubernetes_namespace.update!(namespace: 'old-namespace', service_account_token: nil)
+ end
+
+ it { is_expected.to eq("#{project.path}-#{project.id}") }
+ end
end
context 'when kubernetes namespace is not present' do
@@ -284,6 +298,46 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
{ key: 'KUBE_TOKEN', value: kubernetes_namespace.service_account_token, public: false, masked: true }
)
end
+
+ context 'the cluster has been set to unmanaged after the namespace was created' do
+ before do
+ cluster.update!(managed: false)
+ end
+
+ it_behaves_like 'setting variables'
+
+ it 'sets KUBE_TOKEN from the platform' do
+ expect(subject).to include(
+ { key: 'KUBE_TOKEN', value: kubernetes.token, public: false, masked: true }
+ )
+ end
+
+ context 'the platform has a custom namespace set' do
+ before do
+ kubernetes.update!(namespace: 'custom-namespace')
+ end
+
+ it 'sets KUBE_NAMESPACE from the platform' do
+ expect(subject).to include(
+ { key: 'KUBE_NAMESPACE', value: kubernetes.namespace, public: true, masked: false }
+ )
+ end
+ end
+
+ context 'there is no namespace specified on the platform' do
+ let(:project) { cluster.project }
+
+ before do
+ kubernetes.update!(namespace: nil)
+ end
+
+ it 'sets KUBE_NAMESPACE to a default for the project' do
+ expect(subject).to include(
+ { key: 'KUBE_NAMESPACE', value: "#{project.path}-#{project.id}", public: true, masked: false }
+ )
+ end
+ end
+ end
end
context 'namespace is provided' do
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index 7233d2454c6..379dda1f5c4 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -515,29 +515,19 @@ describe Environment do
context 'when the environment is available' do
context 'with a deployment service' do
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
- context 'and a deployment' do
+ context 'when user configured kubernetes from CI/CD > Clusters' do
+ let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.project }
+
+ context 'with deployment' do
let!(:deployment) { create(:deployment, :success, environment: environment) }
it { is_expected.to be_truthy }
end
- context 'but no deployments' do
+ context 'without deployments' do
it { is_expected.to be_falsy }
end
end
-
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
- context 'when user configured kubernetes from CI/CD > Clusters' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:project) { cluster.project }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
end
context 'without a deployment service' do
@@ -546,8 +536,6 @@ describe Environment do
end
context 'when the environment is unavailable' do
- let(:project) { create(:kubernetes_project) }
-
before do
environment.stop
end
@@ -590,7 +578,10 @@ describe Environment do
allow(environment).to receive(:has_terminals?).and_return(true)
end
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
+ context 'when user configured kubernetes from CI/CD > Clusters' do
+ let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.project }
+
it 'returns the terminals from the deployment service' do
expect(environment.deployment_platform)
.to receive(:terminals).with(environment)
@@ -599,19 +590,6 @@ describe Environment do
is_expected.to eq(:fake_terminals)
end
end
-
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
- context 'when user configured kubernetes from CI/CD > Clusters' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:project) { cluster.project }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
end
context 'when the environment does not have terminals' do
diff --git a/spec/models/lfs_object_spec.rb b/spec/models/lfs_object_spec.rb
index 3d4d4b7d795..85bfc3f1387 100644
--- a/spec/models/lfs_object_spec.rb
+++ b/spec/models/lfs_object_spec.rb
@@ -3,6 +3,20 @@
require 'spec_helper'
describe LfsObject do
+ it 'has a distinct has_many :projects relation through lfs_objects_projects' do
+ lfs_object = create(:lfs_object)
+ project = create(:project)
+ [:project, :design].each do |repository_type|
+ create(:lfs_objects_project, project: project,
+ lfs_object: lfs_object,
+ repository_type: repository_type)
+ end
+
+ expect(lfs_object.lfs_objects_projects.size).to eq(2)
+ expect(lfs_object.projects.size).to eq(1)
+ expect(lfs_object.projects.to_a).to eql([project])
+ end
+
describe '#local_store?' do
it 'returns true when file_store is equal to LfsObjectUploader::Store::LOCAL' do
subject.file_store = LfsObjectUploader::Store::LOCAL
diff --git a/spec/models/lfs_objects_project_spec.rb b/spec/models/lfs_objects_project_spec.rb
index 3e86ee38566..e320f873989 100644
--- a/spec/models/lfs_objects_project_spec.rb
+++ b/spec/models/lfs_objects_project_spec.rb
@@ -20,8 +20,8 @@ describe LfsObjectsProject do
it 'validates object id' do
is_expected.to validate_uniqueness_of(:lfs_object_id)
- .scoped_to(:project_id)
- .with_message("already exists in project")
+ .scoped_to(:project_id, :repository_type)
+ .with_message("already exists in repository")
end
end
diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb
index a04b984c1f6..a1bd0855708 100644
--- a/spec/models/project_services/hipchat_service_spec.rb
+++ b/spec/models/project_services/hipchat_service_spec.rb
@@ -301,7 +301,7 @@ describe HipchatService do
end
context 'pipeline events' do
- let(:pipeline) { create(:ci_empty_pipeline, user: create(:user)) }
+ let(:pipeline) { create(:ci_empty_pipeline, user: project.owner) }
let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
context 'for failed' do
diff --git a/spec/models/project_services/issue_tracker_data_spec.rb b/spec/models/project_services/issue_tracker_data_spec.rb
new file mode 100644
index 00000000000..aaab654f874
--- /dev/null
+++ b/spec/models/project_services/issue_tracker_data_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe IssueTrackerData do
+ let(:service) { create(:custom_issue_tracker_service, active: false, properties: {}) }
+
+ describe 'Associations' do
+ it { is_expected.to belong_to :service }
+ end
+
+ describe 'Validations' do
+ subject { described_class.new(service: service) }
+
+ context 'url validations' do
+ context 'when service is inactive' do
+ it { is_expected.not_to validate_presence_of(:project_url) }
+ it { is_expected.not_to validate_presence_of(:issues_url) }
+ end
+
+ context 'when service is active' do
+ before do
+ service.update(active: true)
+ end
+
+ it_behaves_like 'issue tracker service URL attribute', :project_url
+ it_behaves_like 'issue tracker service URL attribute', :issues_url
+ it_behaves_like 'issue tracker service URL attribute', :new_issue_url
+
+ it { is_expected.to validate_presence_of(:project_url) }
+ it { is_expected.to validate_presence_of(:issues_url) }
+ end
+ end
+ end
+end
diff --git a/spec/models/project_services/jira_tracker_data_spec.rb b/spec/models/project_services/jira_tracker_data_spec.rb
new file mode 100644
index 00000000000..1b6ece8531b
--- /dev/null
+++ b/spec/models/project_services/jira_tracker_data_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe JiraTrackerData do
+ let(:service) { create(:jira_service, active: false, properties: {}) }
+
+ describe 'Associations' do
+ it { is_expected.to belong_to(:service) }
+ end
+
+ describe 'Validations' do
+ subject { described_class.new(service: service) }
+
+ context 'jira_issue_transition_id' do
+ it { is_expected.to allow_value(nil).for(:jira_issue_transition_id) }
+ it { is_expected.to allow_value('1,2,3').for(:jira_issue_transition_id) }
+ it { is_expected.to allow_value('1;2;3').for(:jira_issue_transition_id) }
+ it { is_expected.not_to allow_value('a,b,cd').for(:jira_issue_transition_id) }
+ end
+
+ context 'url validations' do
+ context 'when service is inactive' do
+ it { is_expected.not_to validate_presence_of(:url) }
+ it { is_expected.not_to validate_presence_of(:username) }
+ it { is_expected.not_to validate_presence_of(:password) }
+ end
+
+ context 'when service is active' do
+ before do
+ service.update(active: true)
+ end
+
+ it_behaves_like 'issue tracker service URL attribute', :url
+
+ it { is_expected.to validate_presence_of(:url) }
+ it { is_expected.to validate_presence_of(:username) }
+ it { is_expected.to validate_presence_of(:password) }
+ end
+ end
+ end
+end
diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb
index 2fce120381b..34ee1eafd5c 100644
--- a/spec/models/project_services/kubernetes_service_spec.rb
+++ b/spec/models/project_services/kubernetes_service_spec.rb
@@ -17,6 +17,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
context 'when service is active' do
before do
subject.active = true
+ subject.skip_deprecation_validation = true
end
it { is_expected.not_to validate_presence_of(:namespace) }
@@ -67,6 +68,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
before do
kubernetes_service.update_attribute(:active, false)
+ kubernetes_service.skip_deprecation_validation = false
kubernetes_service.properties['namespace'] = "foo"
end
@@ -80,19 +82,11 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
end
end
- context 'with a non-deprecated service' do
- let(:kubernetes_service) { create(:kubernetes_service) }
-
- it 'updates attributes' do
- kubernetes_service.properties['namespace'] = 'foo'
- expect(kubernetes_service.save).to be_truthy
- end
- end
-
context 'with an active and deprecated service' do
let(:kubernetes_service) { create(:kubernetes_service) }
before do
+ kubernetes_service.skip_deprecation_validation = false
kubernetes_service.active = false
kubernetes_service.properties['namespace'] = 'foo'
kubernetes_service.save
@@ -110,19 +104,6 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
expect(kubernetes_service.properties['namespace']).to eq("foo")
end
end
-
- context 'with a template service' do
- let(:kubernetes_service) { create(:kubernetes_service, template: true, active: false) }
-
- before do
- kubernetes_service.properties['namespace'] = 'foo'
- end
-
- it 'updates attributes' do
- expect(kubernetes_service.save).to be_truthy
- expect(kubernetes_service.properties['namespace']).to eq('foo')
- end
- end
end
describe '#initialize_properties' do
@@ -393,17 +374,8 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
describe "#deprecated?" do
let(:kubernetes_service) { create(:kubernetes_service) }
- context 'with an active kubernetes service' do
- it 'returns false' do
- expect(kubernetes_service.deprecated?).to be_falsy
- end
- end
-
- context 'with a inactive kubernetes service' do
- it 'returns true' do
- kubernetes_service.update_attribute(:active, false)
- expect(kubernetes_service.deprecated?).to be_truthy
- end
+ it 'returns true' do
+ expect(kubernetes_service.deprecated?).to be_truthy
end
end
@@ -414,12 +386,6 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
expect(kubernetes_service.deprecation_message).to match(/Kubernetes service integration has been deprecated/)
end
- context 'if the services is active' do
- it 'returns a message' do
- expect(kubernetes_service.deprecation_message).to match(/Your Kubernetes cluster information on this page is still editable/)
- end
- end
-
context 'if the service is not active' do
it 'returns a message' do
kubernetes_service.update_attribute(:active, false)
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index aad08b9d4aa..20b98b5eb85 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -103,6 +103,20 @@ describe Project do
expect(described_class.reflect_on_association(:merge_requests).has_inverse?).to eq(:target_project)
end
+ it 'has a distinct has_many :lfs_objects relation through lfs_objects_projects' do
+ project = create(:project)
+ lfs_object = create(:lfs_object)
+ [:project, :design].each do |repository_type|
+ create(:lfs_objects_project, project: project,
+ lfs_object: lfs_object,
+ repository_type: repository_type)
+ end
+
+ expect(project.lfs_objects_projects.size).to eq(2)
+ expect(project.lfs_objects.size).to eq(1)
+ expect(project.lfs_objects.to_a).to eql([lfs_object])
+ end
+
context 'after initialized' do
it "has a project_feature" do
expect(described_class.new.project_feature).to be_present
@@ -1479,11 +1493,28 @@ describe Project do
end
context 'when set to INTERNAL in application settings' do
+ using RSpec::Parameterized::TableSyntax
+
before do
stub_application_setting(default_project_visibility: Gitlab::VisibilityLevel::INTERNAL)
end
it { is_expected.to eq(Gitlab::VisibilityLevel::INTERNAL) }
+
+ where(:attribute_name, :value) do
+ :visibility | 'public'
+ :visibility_level | Gitlab::VisibilityLevel::PUBLIC
+ 'visibility' | 'public'
+ 'visibility_level' | Gitlab::VisibilityLevel::PUBLIC
+ end
+
+ with_them do
+ it 'sets the visibility level' do
+ proj = described_class.new(attribute_name => value, name: 'test', path: 'test')
+
+ expect(proj.visibility_level).to eq(Gitlab::VisibilityLevel::PUBLIC)
+ end
+ end
end
end
@@ -2621,7 +2652,10 @@ describe Project do
end
context 'when project has a deployment service' do
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
+ context 'when user configured kubernetes from CI/CD > Clusters and KubernetesNamespace migration has not been executed' do
+ let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.project }
+
it 'returns variables from this service' do
expect(project.deployment_variables).to include(
{ key: 'KUBE_TOKEN', value: project.deployment_platform.token, public: false, masked: true }
@@ -2629,19 +2663,6 @@ describe Project do
end
end
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
- context 'when user configured kubernetes from CI/CD > Clusters and KubernetesNamespace migration has not been executed' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:project) { cluster.project }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
context 'when user configured kubernetes from CI/CD > Clusters and KubernetesNamespace migration has been executed' do
let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token) }
let!(:cluster) { kubernetes_namespace.cluster }
@@ -3447,6 +3468,7 @@ describe Project do
before do
allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
+ stub_application_setting(hashed_storage_enabled: false)
end
describe '#base_dir' do
@@ -3553,10 +3575,6 @@ describe Project do
let(:hashed_prefix) { File.join('@hashed', hash[0..1], hash[2..3]) }
let(:hashed_path) { File.join(hashed_prefix, hash) }
- before do
- stub_application_setting(hashed_storage_enabled: true)
- end
-
describe '#legacy_storage?' do
it 'returns false' do
expect(project.legacy_storage?).to be_falsey
@@ -4698,10 +4716,6 @@ describe Project do
subject { project.object_pool_params }
- before do
- stub_application_setting(hashed_storage_enabled: true)
- end
-
context 'when the objects cannot be pooled' do
let(:project) { create(:project, :repository, :private) }
@@ -4747,10 +4761,6 @@ describe Project do
context 'when objects are poolable' do
let(:project) { create(:project, :repository, :public) }
- before do
- stub_application_setting(hashed_storage_enabled: true)
- end
-
it { is_expected.to be_git_objects_poolable }
end
end
diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb
index 64db32781fe..d442c73c118 100644
--- a/spec/models/service_spec.rb
+++ b/spec/models/service_spec.rb
@@ -6,6 +6,8 @@ describe Service do
describe "Associations" do
it { is_expected.to belong_to :project }
it { is_expected.to have_one :service_hook }
+ it { is_expected.to have_one :jira_tracker_data }
+ it { is_expected.to have_one :issue_tracker_data }
end
describe 'Validations' do
@@ -80,7 +82,7 @@ describe Service do
context 'when template is invalid' do
it 'sets service template to inactive when template is invalid' do
project = create(:project)
- template = KubernetesService.new(template: true, active: true)
+ template = build(:prometheus_service, template: true, active: true, properties: {})
template.save(validate: false)
service = described_class.build_from_template(project.id, template)
@@ -307,10 +309,10 @@ describe Service do
end
describe '.find_by_template' do
- let!(:kubernetes_service) { create(:kubernetes_service, template: true) }
+ let!(:service) { create(:service, template: true) }
it 'returns service template' do
- expect(KubernetesService.find_by_template).to eq(kubernetes_service)
+ expect(described_class.find_by_template).to eq(service)
end
end
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index ed0e82ef179..4b723a52b51 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -39,7 +39,7 @@ describe ProjectPolicy do
admin_milestone admin_merge_request update_merge_request create_commit_status
update_commit_status create_build update_build create_pipeline
update_pipeline create_merge_request_from create_wiki push_code
- resolve_note create_container_image update_container_image
+ resolve_note create_container_image update_container_image destroy_container_image
create_environment create_deployment create_release update_release
]
end
diff --git a/spec/requests/api/container_registry_spec.rb b/spec/requests/api/container_registry_spec.rb
index ea035a8be4a..4ad15ed6bea 100644
--- a/spec/requests/api/container_registry_spec.rb
+++ b/spec/requests/api/container_registry_spec.rb
@@ -201,10 +201,10 @@ describe API::ContainerRegistry do
describe 'DELETE /projects/:id/registry/repositories/:repository_id/tags/:tag_name' do
subject { delete api("/projects/#{project.id}/registry/repositories/#{root_repository.id}/tags/rootA", api_user) }
- it_behaves_like 'being disallowed', :developer
+ it_behaves_like 'being disallowed', :reporter
- context 'for maintainer' do
- let(:api_user) { maintainer }
+ context 'for developer' do
+ let(:api_user) { developer }
before do
stub_container_registry_tags(repository: root_repository.path, tags: %w(rootA), with_manifest: true)
diff --git a/spec/requests/api/graphql/tasks/task_completion_status_spec.rb b/spec/requests/api/graphql/tasks/task_completion_status_spec.rb
new file mode 100644
index 00000000000..c457a6d7c25
--- /dev/null
+++ b/spec/requests/api/graphql/tasks/task_completion_status_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'getting task completion status information' do
+ include GraphqlHelpers
+
+ DESCRIPTION_0_DONE = '- [ ] task 1\n- [ ] task 2'
+ DESCRIPTION_1_DONE = '- [x] task 1\n- [ ] task 2'
+ DESCRIPTION_2_DONE = '- [x] task 1\n- [x] task 2'
+
+ set(:user1) { create(:user) }
+ set(:project) { create(:project, :repository, :public) }
+
+ let(:fields) do
+ <<~QUERY
+ taskCompletionStatus {
+ count,
+ completedCount
+ }
+ QUERY
+ end
+
+ def create_task_completion_status_query_for(type, iid)
+ graphql_query_for(
+ 'project',
+ { 'fullPath' => project.full_path },
+ query_graphql_field(type, { iid: iid }, fields)
+ )
+ end
+
+ shared_examples_for 'graphql task completion status provider' do |type|
+ it 'returns the expected task completion status' do
+ post_graphql(create_task_completion_status_query_for(type, item.iid), current_user: user1)
+
+ expect(response).to have_gitlab_http_status(200)
+
+ task_completion_status = graphql_data.dig('project', type, 'taskCompletionStatus')
+ expect(task_completion_status).not_to be_nil
+ expect(task_completion_status['count']).to eq(item.task_completion_status[:count])
+ expect(task_completion_status['completedCount']).to eq(item.task_completion_status[:completed_count])
+ end
+ end
+
+ [DESCRIPTION_0_DONE, DESCRIPTION_1_DONE, DESCRIPTION_2_DONE].each do |desc|
+ context "with description #{desc}" do
+ context 'when type is issue' do
+ it_behaves_like 'graphql task completion status provider', 'issue' do
+ let(:item) { create(:issue, project: project, description: desc) }
+ end
+ end
+
+ context 'when type is merge request' do
+ it_behaves_like 'graphql task completion status provider', 'mergeRequest' do
+ let(:item) { create(:merge_request, author: user1, source_project: project, description: desc) }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb
index e260aa21e25..3f79e332b90 100644
--- a/spec/requests/api/services_spec.rb
+++ b/spec/requests/api/services_spec.rb
@@ -10,7 +10,10 @@ describe API::Services do
end
Service.available_services_names.each do |service|
- describe "PUT /projects/:id/services/#{service.dasherize}" do
+ # TODO: Remove below `if: (service != "kubernetes")` in the next release
+ # KubernetesService was deprecated and it can't be updated. Right now it's
+ # only readable. It should be completely removed in the next iteration.
+ describe "PUT /projects/:id/services/#{service.dasherize}", if: (service != "kubernetes") do
include_context service
it "updates #{service} settings" do
@@ -19,13 +22,22 @@ describe API::Services do
expect(response).to have_gitlab_http_status(200)
current_service = project.services.first
- event = current_service.event_names.empty? ? "foo" : current_service.event_names.first
- state = current_service[event] || false
+ events = current_service.event_names.empty? ? ["foo"].freeze : current_service.event_names
+ query_strings = []
+ events.each do |event|
+ query_strings << "#{event}=#{!current_service[event]}"
+ end
+ query_strings = query_strings.join('&')
- put api("/projects/#{project.id}/services/#{dashed_service}?#{event}=#{!state}", user), params: service_attrs
+ put api("/projects/#{project.id}/services/#{dashed_service}?#{query_strings}", user), params: service_attrs
expect(response).to have_gitlab_http_status(200)
- expect(project.services.first[event]).not_to eq(state) unless event == "foo"
+ events.each do |event|
+ next if event == "foo"
+
+ expect(project.services.first[event]).not_to eq(current_service[event]),
+ "expected #{!current_service[event]} for event #{event} for service #{current_service.title}, got #{current_service[event]}"
+ end
end
it "returns if required fields missing" do
@@ -50,7 +62,10 @@ describe API::Services do
end
end
- describe "DELETE /projects/:id/services/#{service.dasherize}" do
+ # TODO: Remove below `if: (service != "kubernetes")` in the next release
+ # KubernetesService was deprecated and it can't be updated. Right now it's
+ # only readable. It should be completely removed in the next iteration.
+ describe "DELETE /projects/:id/services/#{service.dasherize}", if: (service != "kubernetes") do
include_context service
before do
diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb
index 49412b628b3..25390f8a23e 100644
--- a/spec/requests/projects/cycle_analytics_events_spec.rb
+++ b/spec/requests/projects/cycle_analytics_events_spec.rb
@@ -32,10 +32,10 @@ describe 'cycle analytics events' do
it 'lists the plan events' do
get project_cycle_analytics_plan_path(project, format: :json)
- first_mr_short_sha = project.merge_requests.sort_by_attribute(:created_asc).first.commits.first.short_id
+ first_issue_iid = project.issues.sort_by_attribute(:created_desc).pluck(:iid).first.to_s
expect(json_response['events']).not_to be_empty
- expect(json_response['events'].first['short_sha']).to eq(first_mr_short_sha)
+ expect(json_response['events'].first['iid']).to eq(first_issue_iid)
end
it 'lists the code events' do
diff --git a/spec/serializers/environment_entity_spec.rb b/spec/serializers/environment_entity_spec.rb
index c2312734042..906449f470b 100644
--- a/spec/serializers/environment_entity_spec.rb
+++ b/spec/serializers/environment_entity_spec.rb
@@ -59,15 +59,5 @@ describe EnvironmentEntity do
expect(subject[:cluster_type]).to eq('project_type')
end
end
-
- context 'when deployment platform is a Kubernetes Service' do
- before do
- create(:kubernetes_service, project: project)
- end
-
- it 'does not include cluster_type' do
- expect(subject).not_to include(:cluster_type)
- end
- end
end
end
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index 867692d4d64..d9b61dfe503 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -1132,5 +1132,17 @@ describe Ci::CreatePipelineService do
.with_message('Insufficient permissions to create a new pipeline')
end
end
+
+ context 'when a user with permissions has been blocked' do
+ before do
+ user.block!
+ end
+
+ it 'raises an error' do
+ expect { subject }
+ .to raise_error(described_class::CreateError)
+ .with_message('Insufficient permissions to create a new pipeline')
+ end
+ end
end
end
diff --git a/spec/services/ci/play_build_service_spec.rb b/spec/services/ci/play_build_service_spec.rb
index 634f865e2d8..1e68b7956ea 100644
--- a/spec/services/ci/play_build_service_spec.rb
+++ b/spec/services/ci/play_build_service_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
describe Ci::PlayBuildService, '#execute' do
- let(:user) { create(:user) }
+ let(:user) { create(:user, developer_projects: [project]) }
let(:project) { create(:project) }
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:build) { create(:ci_build, :manual, pipeline: pipeline) }
@@ -16,8 +16,6 @@ describe Ci::PlayBuildService, '#execute' do
let(:project) { create(:project) }
it 'allows user to play build if protected branch rules are met' do
- project.add_developer(user)
-
create(:protected_branch, :developers_can_merge,
name: build.ref, project: project)
@@ -27,8 +25,6 @@ describe Ci::PlayBuildService, '#execute' do
end
it 'does not allow user with developer role to play build' do
- project.add_developer(user)
-
expect { service.execute(build) }
.to raise_error Gitlab::Access::AccessDeniedError
end
@@ -38,23 +34,21 @@ describe Ci::PlayBuildService, '#execute' do
let(:project) { create(:project, :repository) }
it 'allows user with developer role to play a build' do
- project.add_developer(user)
-
service.execute(build)
expect(build.reload).to be_pending
end
+
+ it 'prevents a blocked developer from playing a build' do
+ user.block!
+
+ expect { service.execute(build) }.to raise_error(Gitlab::Access::AccessDeniedError)
+ end
end
context 'when build is a playable manual action' do
let(:build) { create(:ci_build, :manual, pipeline: pipeline) }
-
- before do
- project.add_developer(user)
-
- create(:protected_branch, :developers_can_merge,
- name: build.ref, project: project)
- end
+ let!(:branch) { create(:protected_branch, :developers_can_merge, name: build.ref, project: project) }
it 'enqueues the build' do
expect(service.execute(build)).to eq build
@@ -70,13 +64,7 @@ describe Ci::PlayBuildService, '#execute' do
context 'when build is not a playable manual action' do
let(:build) { create(:ci_build, when: :manual, pipeline: pipeline) }
-
- before do
- project.add_developer(user)
-
- create(:protected_branch, :developers_can_merge,
- name: build.ref, project: project)
- end
+ let!(:branch) { create(:protected_branch, :developers_can_merge, name: build.ref, project: project) }
it 'duplicates the build' do
duplicate = service.execute(build)
@@ -94,6 +82,7 @@ describe Ci::PlayBuildService, '#execute' do
end
context 'when build is not action' do
+ let(:user) { create(:user) }
let(:build) { create(:ci_build, :success, pipeline: pipeline) }
it 'raises an error' do
@@ -103,10 +92,8 @@ describe Ci::PlayBuildService, '#execute' do
end
context 'when user does not have ability to trigger action' do
- before do
- create(:protected_branch, :no_one_can_push,
- name: build.ref, project: project)
- end
+ let(:user) { create(:user) }
+ let!(:branch) { create(:protected_branch, :developers_can_merge, name: build.ref, project: project) }
it 'raises an error' do
expect { service.execute(build) }
diff --git a/spec/services/lfs/file_transformer_spec.rb b/spec/services/lfs/file_transformer_spec.rb
index 888eea6e91e..9973d64930b 100644
--- a/spec/services/lfs/file_transformer_spec.rb
+++ b/spec/services/lfs/file_transformer_spec.rb
@@ -3,13 +3,13 @@
require "spec_helper"
describe Lfs::FileTransformer do
- let(:project) { create(:project, :repository) }
+ let(:project) { create(:project, :repository, :wiki_repo) }
let(:repository) { project.repository }
let(:file_content) { 'Test file content' }
let(:branch_name) { 'lfs' }
let(:file_path) { 'test_file.lfs' }
- subject { described_class.new(project, branch_name) }
+ subject { described_class.new(project, repository, branch_name) }
describe '#new_file' do
context 'with lfs disabled' do
@@ -100,6 +100,12 @@ describe Lfs::FileTransformer do
end.to change { project.lfs_objects.count }.by(1)
end
+ it 'saves the repository_type to LfsObjectsProject' do
+ subject.new_file(file_path, file_content)
+
+ expect(project.lfs_objects_projects.first.repository_type).to eq('project')
+ end
+
context 'when LfsObject already exists' do
let(:lfs_pointer) { Gitlab::Git::LfsPointerFile.new(file_content) }
@@ -113,6 +119,56 @@ describe Lfs::FileTransformer do
end.to change { project.lfs_objects.count }.by(1)
end
end
+
+ context 'when the LfsObject is already linked to project' do
+ before do
+ subject.new_file(file_path, file_content)
+ end
+
+ shared_examples 'a new LfsObject is not created' do
+ it do
+ expect do
+ second_service.new_file(file_path, file_content)
+ end.not_to change { project.lfs_objects.count }
+ end
+ end
+
+ context 'and the service is called again with the same repository type' do
+ let(:second_service) { described_class.new(project, repository, branch_name) }
+
+ include_examples 'a new LfsObject is not created'
+
+ it 'does not create a new LfsObjectsProject record' do
+ expect do
+ second_service.new_file(file_path, file_content)
+ end.not_to change { project.lfs_objects_projects.count }
+ end
+ end
+
+ context 'and the service is called again with a different repository type' do
+ let(:second_service) { described_class.new(project, project.wiki.repository, branch_name) }
+
+ before do
+ expect(second_service).to receive(:lfs_file?).and_return(true)
+ end
+
+ include_examples 'a new LfsObject is not created'
+
+ it 'creates a new LfsObjectsProject record' do
+ expect do
+ second_service.new_file(file_path, file_content)
+ end.to change { project.lfs_objects_projects.count }.by(1)
+ end
+
+ it 'sets the correct repository_type on the new LfsObjectsProject record' do
+ second_service.new_file(file_path, file_content)
+
+ repository_types = project.lfs_objects_projects.order(:id).pluck(:repository_type)
+
+ expect(repository_types).to eq(%w(project wiki))
+ end
+ end
+ end
end
end
end
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 4b40c86574f..f25e2fe5e2b 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -2217,10 +2217,12 @@ describe NotificationService, :mailer do
let(:pipeline) { create(:ci_pipeline, :failed, project: project, user: pipeline_user) }
it 'emails project owner and user that triggered the pipeline' do
+ project.add_developer(pipeline_user)
+
notification.autodevops_disabled(pipeline, [owner.email, pipeline_user.email])
- should_email(owner)
- should_email(pipeline_user)
+ should_email(owner, times: 1) # Once for the disable pipeline.
+ should_email(pipeline_user, times: 2) # Once for the new permission, once for the disable.
end
end
end
diff --git a/spec/services/projects/after_rename_service_spec.rb b/spec/services/projects/after_rename_service_spec.rb
index b8055a285f2..8585d495ffb 100644
--- a/spec/services/projects/after_rename_service_spec.rb
+++ b/spec/services/projects/after_rename_service_spec.rb
@@ -23,6 +23,7 @@ describe Projects::AfterRenameService do
allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
stub_feature_flags(skip_hashed_storage_upgrade: false)
+ stub_application_setting(hashed_storage_enabled: false)
end
it 'renames a repository' do
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index f54f9200661..b0b74407812 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -152,6 +152,33 @@ describe Projects::CreateService, '#execute' do
end
end
+ context 'default visibility level' do
+ let(:group) { create(:group, :private) }
+
+ before do
+ stub_application_setting(default_project_visibility: Gitlab::VisibilityLevel::INTERNAL)
+ group.add_developer(user)
+
+ opts.merge!(
+ visibility: 'private',
+ name: 'test',
+ namespace: group,
+ path: 'foo'
+ )
+ end
+
+ it 'creates a private project' do
+ project = create_project(user, opts)
+
+ expect(project).to respond_to(:errors)
+
+ expect(project.errors.any?).to be(false)
+ expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
+ expect(project.saved?).to be(true)
+ expect(project.valid?).to be(true)
+ end
+ end
+
context 'restricted visibility level' do
before do
stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
@@ -201,6 +228,7 @@ describe Projects::CreateService, '#execute' do
context 'with legacy storage' do
before do
+ stub_application_setting(hashed_storage_enabled: false)
gitlab_shell.create_repository(repository_storage, "#{user.namespace.full_path}/existing", 'group/project')
end
@@ -232,7 +260,6 @@ describe Projects::CreateService, '#execute' do
let(:hashed_path) { '@hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b' }
before do
- stub_application_setting(hashed_storage_enabled: true)
allow(Digest::SHA2).to receive(:hexdigest) { hash }
end
diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb
index 6afc91d5e95..0c109e26a6a 100644
--- a/spec/services/projects/fork_service_spec.rb
+++ b/spec/services/projects/fork_service_spec.rb
@@ -116,11 +116,12 @@ describe Projects::ForkService do
end
end
- context 'repository already exists' do
+ context 'repository in legacy storage already exists' do
let(:repository_storage) { 'default' }
let(:repository_storage_path) { Gitlab.config.repositories.storages[repository_storage].legacy_disk_path }
before do
+ stub_application_setting(hashed_storage_enabled: false)
gitlab_shell.create_repository(repository_storage, "#{@to_user.namespace.full_path}/#{@from_project.path}", "#{@to_user.namespace.full_path}/#{@from_project.path}")
end
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index e95c7f2a6d6..bcf6669f37d 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -157,7 +157,7 @@ module GraphqlHelpers
when Array # multiplexed queries
json_response.map { |response| response['errors'] }
else
- raise "Unkown GraphQL response type #{json_response.class}"
+ raise "Unknown GraphQL response type #{json_response.class}"
end
end
diff --git a/spec/support/helpers/query_recorder.rb b/spec/support/helpers/query_recorder.rb
index c4ae62b25e4..d45377267f3 100644
--- a/spec/support/helpers/query_recorder.rb
+++ b/spec/support/helpers/query_recorder.rb
@@ -11,7 +11,7 @@ module ActiveRecord
def show_backtrace(values)
Rails.logger.debug("QueryRecorder SQL: #{values[:sql]}")
- caller.each { |line| Rails.logger.debug(" --> #{line}") }
+ Gitlab::Profiler.clean_backtrace(caller).each { |line| Rails.logger.debug(" --> #{line}") }
end
def callback(name, start, finish, message_id, values)
diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb
index 06b5ecdf150..77f22d9dd24 100644
--- a/spec/support/helpers/test_env.rb
+++ b/spec/support/helpers/test_env.rb
@@ -146,19 +146,6 @@ module TestEnv
install_dir: Gitlab.config.gitlab_shell.path,
version: Gitlab::Shell.version_required,
task: 'gitlab:shell:install')
-
- # gitlab-shell hooks don't work in our test environment because they try to make internal API calls
- sabotage_gitlab_shell_hooks
- end
-
- def sabotage_gitlab_shell_hooks
- create_fake_git_hooks(Gitlab::Shell.new.hooks_path)
- end
-
- def create_fake_git_hooks(hooks_dir)
- %w[pre-receive post-receive update].each do |hook|
- File.open(File.join(hooks_dir, hook), 'w', 0755) { |f| f.puts '#!/bin/sh' }
- end
end
def setup_gitaly
@@ -172,7 +159,6 @@ module TestEnv
task: "gitlab:gitaly:install[#{install_gitaly_args}]") do
Gitlab::SetupHelper.create_gitaly_configuration(gitaly_dir, { 'default' => repos_path }, force: true)
- create_fake_git_hooks(File.join(gitaly_dir, 'ruby/git-hooks'))
start_gitaly(gitaly_dir)
end
end
diff --git a/spec/support/prometheus/additional_metrics_shared_examples.rb b/spec/support/prometheus/additional_metrics_shared_examples.rb
index 8044b061ca5..de21e808932 100644
--- a/spec/support/prometheus/additional_metrics_shared_examples.rb
+++ b/spec/support/prometheus/additional_metrics_shared_examples.rb
@@ -44,7 +44,9 @@ RSpec.shared_examples 'additional metrics query' do
end
describe 'project has Kubernetes service' do
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
+ context 'when user configured kubernetes from CI/CD > Clusters' do
+ let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.project }
let(:environment) { create(:environment, slug: 'environment-slug', project: project) }
let(:kube_namespace) { project.deployment_platform.kubernetes_namespace_for(project) }
@@ -56,19 +58,6 @@ RSpec.shared_examples 'additional metrics query' do
subject.query(*query_params)
end
end
-
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
- context 'when user configured kubernetes from CI/CD > Clusters' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:project) { cluster.project }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
end
describe 'project without Kubernetes service' do
diff --git a/spec/support/shared_contexts/services_shared_context.rb b/spec/support/shared_contexts/services_shared_context.rb
index 089f1798cd2..0c3a24d206f 100644
--- a/spec/support/shared_contexts/services_shared_context.rb
+++ b/spec/support/shared_contexts/services_shared_context.rb
@@ -37,8 +37,7 @@ Service.available_services_names.each do |service|
def initialize_service(service)
service_item = project.find_or_initialize_service(service)
service_item.properties = service_attrs
- service_item.active = true if service == "kubernetes"
- service_item.save
+ service_item.save!
service_item
end
end
diff --git a/spec/support/shared_examples/ci_trace_shared_examples.rb b/spec/support/shared_examples/ci_trace_shared_examples.rb
index db935bcb388..f985b2dcbba 100644
--- a/spec/support/shared_examples/ci_trace_shared_examples.rb
+++ b/spec/support/shared_examples/ci_trace_shared_examples.rb
@@ -5,11 +5,11 @@ shared_examples_for 'common trace features' do
end
it "returns formatted html" do
- expect(trace.html).to eq("12<br>34")
+ expect(trace.html).to eq("<span class=\"\">12<br/><span class=\"\">34</span></span>")
end
it "returns last line of formatted html" do
- expect(trace.html(last_lines: 1)).to eq("34")
+ expect(trace.html(last_lines: 1)).to eq("<span class=\"\">34</span>")
end
end
diff --git a/spec/views/notify/pipeline_failed_email.html.haml_spec.rb b/spec/views/notify/pipeline_failed_email.html.haml_spec.rb
index d04affc7df1..623237b111a 100644
--- a/spec/views/notify/pipeline_failed_email.html.haml_spec.rb
+++ b/spec/views/notify/pipeline_failed_email.html.haml_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe 'notify/pipeline_failed_email.html.haml' do
include Devise::Test::ControllerHelpers
- let(:user) { create(:user) }
+ let(:user) { create(:user, developer_projects: [project]) }
let(:project) { create(:project, :repository) }
let(:merge_request) { create(:merge_request, :simple, source_project: project) }
diff --git a/spec/views/notify/pipeline_failed_email.text.erb_spec.rb b/spec/views/notify/pipeline_failed_email.text.erb_spec.rb
index 079fb865d7b..81245239eba 100644
--- a/spec/views/notify/pipeline_failed_email.text.erb_spec.rb
+++ b/spec/views/notify/pipeline_failed_email.text.erb_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
describe 'notify/pipeline_failed_email.text.erb' do
include Devise::Test::ControllerHelpers
- let(:user) { create(:user) }
+ let(:user) { create(:user, developer_projects: [project]) }
let(:project) { create(:project, :repository) }
let(:merge_request) { create(:merge_request, :simple, source_project: project) }
diff --git a/spec/views/notify/pipeline_success_email.html.haml_spec.rb b/spec/views/notify/pipeline_success_email.html.haml_spec.rb
index 8ee7f954d70..a876bf13e11 100644
--- a/spec/views/notify/pipeline_success_email.html.haml_spec.rb
+++ b/spec/views/notify/pipeline_success_email.html.haml_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe 'notify/pipeline_success_email.html.haml' do
include Devise::Test::ControllerHelpers
- let(:user) { create(:user) }
+ let(:user) { create(:user, developer_projects: [project]) }
let(:project) { create(:project, :repository) }
let(:merge_request) { create(:merge_request, :simple, source_project: project) }
diff --git a/spec/views/projects/commit/_commit_box.html.haml_spec.rb b/spec/views/projects/commit/_commit_box.html.haml_spec.rb
index 457dd2e940f..1086546c10d 100644
--- a/spec/views/projects/commit/_commit_box.html.haml_spec.rb
+++ b/spec/views/projects/commit/_commit_box.html.haml_spec.rb
@@ -27,7 +27,7 @@ describe 'projects/commit/_commit_box.html.haml' do
render
- expect(rendered).to have_text("Pipeline ##{third_pipeline.id} (##{third_pipeline.iid}) failed")
+ expect(rendered).to have_text("Pipeline ##{third_pipeline.id} failed")
end
end
@@ -40,7 +40,7 @@ describe 'projects/commit/_commit_box.html.haml' do
it 'shows correct pipeline description' do
render
- expect(rendered).to have_text "Pipeline ##{pipeline.id} (##{pipeline.iid}) " \
+ expect(rendered).to have_text "Pipeline ##{pipeline.id} " \
'waiting for manual action'
end
end
diff --git a/spec/views/projects/jobs/_build.html.haml_spec.rb b/spec/views/projects/jobs/_build.html.haml_spec.rb
index 97b25a6976f..1d58891036e 100644
--- a/spec/views/projects/jobs/_build.html.haml_spec.rb
+++ b/spec/views/projects/jobs/_build.html.haml_spec.rb
@@ -4,7 +4,7 @@ describe 'projects/ci/jobs/_build' do
include Devise::Test::ControllerHelpers
let(:project) { create(:project, :repository) }
- let(:pipeline) { create(:ci_empty_pipeline, id: 1337, iid: 57, project: project, sha: project.commit.id) }
+ let(:pipeline) { create(:ci_empty_pipeline, id: 1337, project: project, sha: project.commit.id) }
let(:build) { create(:ci_build, pipeline: pipeline, stage: 'test', stage_idx: 1, name: 'rspec 0:2', status: :pending) }
before do
@@ -15,14 +15,14 @@ describe 'projects/ci/jobs/_build' do
it 'won\'t include a column with a link to its pipeline by default' do
render partial: 'projects/ci/builds/build', locals: { build: build }
- expect(rendered).not_to have_link('#1337 (#57)')
- expect(rendered).not_to have_text('#1337 (#57) by API')
+ expect(rendered).not_to have_link('#1337')
+ expect(rendered).not_to have_text('#1337 by API')
end
it 'can include a column with a link to its pipeline' do
render partial: 'projects/ci/builds/build', locals: { build: build, pipeline_link: true }
- expect(rendered).to have_link('#1337 (#57)')
- expect(rendered).to have_text('#1337 (#57) by API')
+ expect(rendered).to have_link('#1337')
+ expect(rendered).to have_text('#1337 by API')
end
end
diff --git a/spec/workers/auto_devops/disable_worker_spec.rb b/spec/workers/auto_devops/disable_worker_spec.rb
index 800a07e41a5..53113f286ba 100644
--- a/spec/workers/auto_devops/disable_worker_spec.rb
+++ b/spec/workers/auto_devops/disable_worker_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
describe AutoDevops::DisableWorker, '#perform' do
- let(:user) { create(:user) }
+ let(:user) { create(:user, developer_projects: [project]) }
let(:project) { create(:project, :repository, :auto_devops) }
let(:auto_devops) { project.auto_devops }
let(:pipeline) { create(:ci_pipeline, :failed, :auto_devops_source, project: project, user: user) }
@@ -10,6 +10,7 @@ describe AutoDevops::DisableWorker, '#perform' do
subject { described_class.new }
before do
+ project.add_developer(user)
stub_application_setting(auto_devops_enabled: true)
auto_devops.update_attribute(:enabled, nil)
end
diff --git a/spec/workers/reactive_caching_worker_spec.rb b/spec/workers/reactive_caching_worker_spec.rb
index 2395e6ec947..b8ca6063ccd 100644
--- a/spec/workers/reactive_caching_worker_spec.rb
+++ b/spec/workers/reactive_caching_worker_spec.rb
@@ -6,16 +6,6 @@ describe ReactiveCachingWorker do
let(:service) { project.deployment_platform }
describe '#perform' do
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project) }
-
- it 'calls #exclusively_update_reactive_cache!' do
- expect_any_instance_of(KubernetesService).to receive(:exclusively_update_reactive_cache!)
-
- described_class.new.perform("KubernetesService", service.id)
- end
- end
-
context 'when user configured kubernetes from CI/CD > Clusters' do
let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:project) { cluster.project }