summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Hughes <me@iamphill.com>2018-04-30 09:09:17 +0100
committerPhil Hughes <me@iamphill.com>2018-04-30 09:09:17 +0100
commitbc3f710ef382967269a425c4970eab71428a9745 (patch)
tree2e3307c2d69cab98629bfde491f7049377c76c11
parent15a8535f4a95723abfe1b3f112604b7388691f42 (diff)
parent26630b9f8ddb7668d7d7527287d4f8ee920fde37 (diff)
downloadgitlab-ce-bc3f710ef382967269a425c4970eab71428a9745.tar.gz
Merge branch '44846-improve-web-ide-left-panel-and-modes' into ide-activity-bar-review-mode
-rw-r--r--.gitignore1
-rw-r--r--.gitlab-ci.yml20
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--app/finders/pipelines_finder.rb9
-rw-r--r--app/services/system_note_service.rb2
-rw-r--r--app/views/projects/protected_branches/_create_protected_branch.html.haml4
-rw-r--r--app/views/projects/protected_branches/_update_protected_branch.html.haml2
-rw-r--r--app/views/projects/settings/ci_cd/_autodevops_form.html.haml1
-rw-r--r--changelogs/unreleased/jramsay-44880-filter-pipelines-by-sha.yml5
-rw-r--r--changelogs/unreleased/zj-repository-exist-mandatory.yml5
-rw-r--r--config/gitlab.yml.example20
-rw-r--r--config/initializers/1_settings.rb3
-rw-r--r--config/initializers/pages.rb2
-rw-r--r--doc/api/pipelines.md1
-rw-r--r--doc/topics/autodevops/index.md5
-rw-r--r--lib/api/pipelines.rb1
-rw-r--r--lib/gitlab/git/repository.rb10
-rw-r--r--lib/gitlab/pages_client.rb117
-rw-r--r--lib/tasks/gitlab/pages.rake9
-rw-r--r--qa/qa/factory/repository/push.rb4
-rw-r--r--qa/qa/factory/resource/branch.rb19
-rw-r--r--qa/qa/page/project/settings/protected_branches.rb29
-rw-r--r--qa/qa/runtime/key/ecdsa.rb1
-rw-r--r--qa/qa/runtime/key/ed25519.rb1
-rw-r--r--qa/qa/specs/features/repository/protected_branches_spec.rb7
-rw-r--r--spec/features/projects/tree/upload_file_spec.rb13
-rw-r--r--spec/finders/pipelines_finder_spec.rb20
-rw-r--r--spec/lib/gitlab/pages_client_spec.rb172
-rw-r--r--spec/models/repository_spec.rb16
-rw-r--r--spec/services/system_note_service_spec.rb8
30 files changed, 438 insertions, 71 deletions
diff --git a/.gitignore b/.gitignore
index e9ff0048c1c..e1561c9db9a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -72,3 +72,4 @@ eslint-report.html
/locale/**/*.time_stamp
/.rspec
/plugins/*
+/.gitlab_pages_secret
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5bc2f1f3a0f..05487134cb1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -110,7 +110,7 @@ stages:
# Jobs that only need to pull cache
.dedicated-no-docs-pull-cache-job: &dedicated-no-docs-pull-cache-job
<<: *dedicated-runner
- <<: *except-docs-and-qa
+ <<: *except-docs
<<: *pull-cache
dependencies:
- setup-test-env
@@ -122,6 +122,10 @@ stages:
variables:
SETUP_DB: "false"
+.dedicated-no-docs-and-no-qa-pull-cache-job: &dedicated-no-docs-and-no-qa-pull-cache-job
+ <<: *dedicated-no-docs-pull-cache-job
+ <<: *except-docs-and-qa
+
.rake-exec: &rake-exec
<<: *dedicated-no-docs-no-db-pull-cache-job
script:
@@ -222,7 +226,7 @@ stages:
- master@gitlab/gitlab-ee
.gitlab-setup: &gitlab-setup
- <<: *dedicated-no-docs-pull-cache-job
+ <<: *dedicated-no-docs-and-no-qa-pull-cache-job
<<: *use-pg
variables:
CREATE_DB_USER: "true"
@@ -262,12 +266,12 @@ stages:
# DB migration, rollback, and seed jobs
.db-migrate-reset: &db-migrate-reset
- <<: *dedicated-no-docs-pull-cache-job
+ <<: *dedicated-no-docs-and-no-qa-pull-cache-job
script:
- bundle exec rake db:migrate:reset
.migration-paths: &migration-paths
- <<: *dedicated-no-docs-pull-cache-job
+ <<: *dedicated-no-docs-and-no-qa-pull-cache-job
variables:
CREATE_DB_USER: "true"
script:
@@ -647,7 +651,7 @@ migration:path-mysql:
<<: *use-mysql
.db-rollback: &db-rollback
- <<: *dedicated-no-docs-pull-cache-job
+ <<: *dedicated-no-docs-and-no-qa-pull-cache-job
script:
- bundle exec rake db:migrate VERSION=20170523121229
- bundle exec rake db:migrate
@@ -670,7 +674,7 @@ gitlab:setup-mysql:
# Frontend-related jobs
gitlab:assets:compile:
- <<: *dedicated-no-docs-no-db-pull-cache-job
+ <<: *dedicated-no-docs-and-no-qa-pull-cache-job
dependencies: []
variables:
NODE_ENV: "production"
@@ -691,7 +695,7 @@ gitlab:assets:compile:
- webpack-report/
karma:
- <<: *dedicated-no-docs-pull-cache-job
+ <<: *dedicated-no-docs-and-no-qa-pull-cache-job
<<: *use-pg
dependencies:
- compile-assets
@@ -815,7 +819,7 @@ coverage:
- coverage/assets/
lint:javascript:report:
- <<: *dedicated-no-docs-no-db-pull-cache-job
+ <<: *dedicated-no-docs-and-no-qa-pull-cache-job
stage: post-test
dependencies:
- compile-assets
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index a3df0a6959e..ac39a106c48 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-0.8.0
+0.9.0
diff --git a/app/finders/pipelines_finder.rb b/app/finders/pipelines_finder.rb
index f187a3b61fe..0a487839aff 100644
--- a/app/finders/pipelines_finder.rb
+++ b/app/finders/pipelines_finder.rb
@@ -14,6 +14,7 @@ class PipelinesFinder
items = by_scope(items)
items = by_status(items)
items = by_ref(items)
+ items = by_sha(items)
items = by_name(items)
items = by_username(items)
items = by_yaml_errors(items)
@@ -69,6 +70,14 @@ class PipelinesFinder
end
end
+ def by_sha(items)
+ if params[:sha].present?
+ items.where(sha: params[:sha])
+ else
+ items
+ end
+ end
+
def by_name(items)
if params[:name].present?
items.joins(:user).where(users: { name: params[:name] })
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index 958ef065012..00bf5434b7f 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -159,7 +159,7 @@ module SystemNoteService
body = if noteable.time_estimate == 0
"removed time estimate"
else
- "changed time estimate to #{parsed_time},"
+ "changed time estimate to #{parsed_time}"
end
create_note(NoteSummary.new(noteable, project, author, body, action: 'time_tracking'))
diff --git a/app/views/projects/protected_branches/_create_protected_branch.html.haml b/app/views/projects/protected_branches/_create_protected_branch.html.haml
index 12ccae10260..24b53555cdc 100644
--- a/app/views/projects/protected_branches/_create_protected_branch.html.haml
+++ b/app/views/projects/protected_branches/_create_protected_branch.html.haml
@@ -1,8 +1,8 @@
- content_for :merge_access_levels do
.merge_access_levels-container
= dropdown_tag('Select',
- options: { toggle_class: 'js-allowed-to-merge wide',
- dropdown_class: 'dropdown-menu-selectable capitalize-header',
+ options: { toggle_class: 'js-allowed-to-merge qa-allowed-to-merge-select wide',
+ dropdown_class: 'dropdown-menu-selectable qa-allowed-to-merge-dropdown capitalize-header',
data: { field_name: 'protected_branch[merge_access_levels_attributes][0][access_level]', input_id: 'merge_access_levels_attributes' }})
- content_for :push_access_levels do
.push_access_levels-container
diff --git a/app/views/projects/protected_branches/_update_protected_branch.html.haml b/app/views/projects/protected_branches/_update_protected_branch.html.haml
index 98363f2018a..f242459f69b 100644
--- a/app/views/projects/protected_branches/_update_protected_branch.html.haml
+++ b/app/views/projects/protected_branches/_update_protected_branch.html.haml
@@ -1,7 +1,7 @@
%td
= hidden_field_tag "allowed_to_merge_#{protected_branch.id}", protected_branch.merge_access_levels.first.access_level
= dropdown_tag( (protected_branch.merge_access_levels.first.humanize || 'Select') ,
- options: { toggle_class: 'js-allowed-to-merge', dropdown_class: 'dropdown-menu-selectable js-allowed-to-merge-container capitalize-header',
+ options: { toggle_class: 'js-allowed-to-merge qa-allowed-to-merge', dropdown_class: 'dropdown-menu-selectable js-allowed-to-merge-container capitalize-header',
data: { field_name: "allowed_to_merge_#{protected_branch.id}", access_level_id: protected_branch.merge_access_levels.first.id }})
%td
= hidden_field_tag "allowed_to_push_#{protected_branch.id}", protected_branch.push_access_levels.first.access_level
diff --git a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
index 7b410101c05..71e77dae69e 100644
--- a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
@@ -36,5 +36,6 @@
= form.text_field :domain, class: 'form-control', placeholder: 'domain.com'
.help-block
= s_('CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages.')
+ = link_to icon('question-circle'), help_page_path('topics/autodevops/index.md', anchor: 'auto-devops-base-domain'), target: '_blank'
= f.submit 'Save changes', class: "btn btn-success prepend-top-15"
diff --git a/changelogs/unreleased/jramsay-44880-filter-pipelines-by-sha.yml b/changelogs/unreleased/jramsay-44880-filter-pipelines-by-sha.yml
new file mode 100644
index 00000000000..3654aa28ff4
--- /dev/null
+++ b/changelogs/unreleased/jramsay-44880-filter-pipelines-by-sha.yml
@@ -0,0 +1,5 @@
+---
+title: Add sha filter to pipelines list API
+merge_request: 18125
+author:
+type: changed
diff --git a/changelogs/unreleased/zj-repository-exist-mandatory.yml b/changelogs/unreleased/zj-repository-exist-mandatory.yml
new file mode 100644
index 00000000000..7d83446e90f
--- /dev/null
+++ b/changelogs/unreleased/zj-repository-exist-mandatory.yml
@@ -0,0 +1,5 @@
+---
+title: Repository#exists? is always executed through Gitaly
+merge_request:
+author:
+type: performance
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 8c39a1f2aa9..6aad8e93dcc 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -184,18 +184,18 @@ production: &base
# base_dir: uploads/-/system
object_store:
enabled: false
- # remote_directory: uploads # Bucket name
+ remote_directory: uploads # Bucket name
# direct_upload: false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false)
# background_upload: false # Temporary option to limit automatic upload (Default: true)
# proxy_download: false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage
- connection:
- provider: AWS
- aws_access_key_id: AWS_ACCESS_KEY_ID
- aws_secret_access_key: AWS_SECRET_ACCESS_KEY
- region: us-east-1
- # host: 'localhost' # default: s3.amazonaws.com
- # endpoint: 'http://127.0.0.1:9000' # default: nil
- # path_style: true # Use 'host/bucket_name/object' instead of 'bucket_name.host/object'
+ connection:
+ provider: AWS
+ aws_access_key_id: AWS_ACCESS_KEY_ID
+ aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+ region: us-east-1
+ # host: 'localhost' # default: s3.amazonaws.com
+ # endpoint: 'http://127.0.0.1:9000' # default: nil
+ # path_style: true # Use 'host/bucket_name/object' instead of 'bucket_name.host/object'
## GitLab Pages
pages:
@@ -212,6 +212,8 @@ production: &base
artifacts_server: true
# external_http: ["1.1.1.1:80", "[2001::1]:80"] # If defined, enables custom domain support in GitLab Pages
# external_https: ["1.1.1.1:443", "[2001::1]:443"] # If defined, enables custom domain and certificate support in GitLab Pages
+ admin:
+ address: unix:/home/git/gitlab/tmp/sockets/private/pages-admin.socket # TCP connections are supported too (e.g. tcp://host:port)
## Mattermost
## For enabling Add to Mattermost button
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 575f27d1ea9..5248bd858a0 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -215,6 +215,9 @@ Settings.pages['external_http'] ||= false unless Settings.pages['external_ht
Settings.pages['external_https'] ||= false unless Settings.pages['external_https'].present?
Settings.pages['artifacts_server'] ||= Settings.pages['enabled'] if Settings.pages['artifacts_server'].nil?
+Settings.pages['admin'] ||= Settingslogic.new({})
+Settings.pages.admin['certificate'] ||= ''
+
#
# Git LFS
#
diff --git a/config/initializers/pages.rb b/config/initializers/pages.rb
new file mode 100644
index 00000000000..835197557e8
--- /dev/null
+++ b/config/initializers/pages.rb
@@ -0,0 +1,2 @@
+Gitlab::PagesClient.read_or_create_token
+Gitlab::PagesClient.load_certificate
diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md
index a6631cab8c3..899f5da6647 100644
--- a/doc/api/pipelines.md
+++ b/doc/api/pipelines.md
@@ -14,6 +14,7 @@ GET /projects/:id/pipelines
| `scope` | string | no | The scope of pipelines, one of: `running`, `pending`, `finished`, `branches`, `tags` |
| `status` | string | no | The status of pipelines, one of: `running`, `pending`, `success`, `failed`, `canceled`, `skipped` |
| `ref` | string | no | The ref of pipelines |
+| `sha` | string | no | The sha or pipelines |
| `yaml_errors`| boolean | no | Returns pipelines with invalid configurations |
| `name`| string | no | The name of the user who triggered pipelines |
| `username`| string | no | The username of the user who triggered pipelines |
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index 8c4a2925356..7c0cd2c40d2 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -135,6 +135,11 @@ and `1.2.3.4` is the IP address of your load balancer; generally NGINX
([see prerequisites](#prerequisites)). How to set up the DNS record is beyond
the scope of this document; you should check with your DNS provider.
+Alternatively you can use free public services like [xip.io](http://xip.io) or
+[nip.io](http://nip.io) which provide automatic wildcard DNS without any
+configuration. Just set the Auto DevOps base domain to `1.2.3.4.xip.io` or
+`1.2.3.4.nip.io`.
+
Once set up, all requests will hit the load balancer, which in turn will route
them to the Kubernetes pods that run your application(s).
diff --git a/lib/api/pipelines.rb b/lib/api/pipelines.rb
index d2b8b832e4e..735591fedd5 100644
--- a/lib/api/pipelines.rb
+++ b/lib/api/pipelines.rb
@@ -19,6 +19,7 @@ module API
optional :status, type: String, values: HasStatus::AVAILABLE_STATUSES,
desc: 'The status of pipelines'
optional :ref, type: String, desc: 'The ref of pipelines'
+ optional :sha, type: String, desc: 'The sha of pipelines'
optional :yaml_errors, type: Boolean, desc: 'Returns pipelines with invalid configurations'
optional :name, type: String, desc: 'The name of the user who triggered pipelines'
optional :username, type: String, desc: 'The username of the user who triggered pipelines'
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 5a6e2e0b937..0d07fb85213 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -142,15 +142,7 @@ module Gitlab
end
def exists?
- Gitlab::GitalyClient.migrate(:repository_exists, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |enabled|
- if enabled
- gitaly_repository_client.exists?
- else
- circuit_breaker.perform do
- File.exist?(File.join(path, 'refs'))
- end
- end
- end
+ gitaly_repository_client.exists?
end
# Returns an Array of branch names
diff --git a/lib/gitlab/pages_client.rb b/lib/gitlab/pages_client.rb
new file mode 100644
index 00000000000..7b358a3bd1b
--- /dev/null
+++ b/lib/gitlab/pages_client.rb
@@ -0,0 +1,117 @@
+module Gitlab
+ class PagesClient
+ class << self
+ attr_reader :certificate, :token
+
+ def call(service, rpc, request, timeout: nil)
+ kwargs = request_kwargs(timeout)
+ stub(service).__send__(rpc, request, kwargs) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ # This function is not thread-safe. Call it from an initializer only.
+ def read_or_create_token
+ @token = read_token
+ rescue Errno::ENOENT
+ # TODO: uncomment this when omnibus knows how to write the token file for us
+ # https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/2466
+ #
+ # write_token(SecureRandom.random_bytes(64))
+ #
+ # # Read from disk in case someone else won the race and wrote the file
+ # # before us. If this fails again let the exception bubble up.
+ # @token = read_token
+ end
+
+ # This function is not thread-safe. Call it from an initializer only.
+ def load_certificate
+ cert_path = config.certificate
+ return unless cert_path.present?
+
+ @certificate = File.read(cert_path)
+ end
+
+ def ping
+ request = Grpc::Health::V1::HealthCheckRequest.new
+ call(:health_check, :check, request, timeout: 5.seconds)
+ end
+
+ private
+
+ def request_kwargs(timeout)
+ encoded_token = Base64.strict_encode64(token.to_s)
+ metadata = {
+ 'authorization' => "Bearer #{encoded_token}"
+ }
+
+ result = { metadata: metadata }
+
+ return result unless timeout
+
+ # Do not use `Time.now` for deadline calculation, since it
+ # will be affected by Timecop in some tests, but grpc's c-core
+ # uses system time instead of timecop's time, so tests will fail
+ # `Time.at(Process.clock_gettime(Process::CLOCK_REALTIME))` will
+ # circumvent timecop
+ deadline = Time.at(Process.clock_gettime(Process::CLOCK_REALTIME)) + timeout
+ result[:deadline] = deadline
+
+ result
+ end
+
+ def stub(name)
+ stub_class(name).new(address, grpc_creds)
+ end
+
+ def stub_class(name)
+ if name == :health_check
+ Grpc::Health::V1::Health::Stub
+ else
+ # TODO use pages namespace
+ Gitaly.const_get(name.to_s.camelcase.to_sym).const_get(:Stub)
+ end
+ end
+
+ def address
+ addr = config.address
+ addr = addr.sub(%r{^tcp://}, '') if URI(addr).scheme == 'tcp'
+ addr
+ end
+
+ def grpc_creds
+ if address.start_with?('unix:')
+ :this_channel_is_insecure
+ elsif @certificate
+ GRPC::Core::ChannelCredentials.new(@certificate)
+ else
+ # Use system certificate pool
+ GRPC::Core::ChannelCredentials.new
+ end
+ end
+
+ def config
+ Gitlab.config.pages.admin
+ end
+
+ def read_token
+ File.read(token_path)
+ end
+
+ def token_path
+ Rails.root.join('.gitlab_pages_secret').to_s
+ end
+
+ def write_token(new_token)
+ Tempfile.open(File.basename(token_path), File.dirname(token_path), encoding: 'ascii-8bit') do |f|
+ f.write(new_token)
+ f.close
+ File.link(f.path, token_path)
+ end
+ rescue Errno::EACCES => ex
+ # TODO stop rescuing this exception in GitLab 11.0 https://gitlab.com/gitlab-org/gitlab-ce/issues/45672
+ Rails.logger.error("Could not write pages admin token file: #{ex}")
+ rescue Errno::EEXIST
+ # Another process wrote the token file concurrently with us. Use their token, not ours.
+ end
+ end
+ end
+end
diff --git a/lib/tasks/gitlab/pages.rake b/lib/tasks/gitlab/pages.rake
new file mode 100644
index 00000000000..100e480bd66
--- /dev/null
+++ b/lib/tasks/gitlab/pages.rake
@@ -0,0 +1,9 @@
+namespace :gitlab do
+ namespace :pages do
+ desc 'Ping the pages admin API'
+ task admin_ping: :gitlab_environment do
+ Gitlab::PagesClient.ping
+ puts "OK: gitlab-pages admin API is reachable"
+ end
+ end
+end
diff --git a/qa/qa/factory/repository/push.rb b/qa/qa/factory/repository/push.rb
index 01a9d0428ea..795f1f9cb1a 100644
--- a/qa/qa/factory/repository/push.rb
+++ b/qa/qa/factory/repository/push.rb
@@ -3,7 +3,9 @@ module QA
module Repository
class Push < Factory::Base
attr_accessor :file_name, :file_content, :commit_message,
- :branch_name, :new_branch, :remote_branch
+ :branch_name, :new_branch
+
+ attr_writer :remote_branch
dependency Factory::Resource::Project, as: :project do |project|
project.name = 'project-with-code'
diff --git a/qa/qa/factory/resource/branch.rb b/qa/qa/factory/resource/branch.rb
index d6bfdfa2356..1785441f5a8 100644
--- a/qa/qa/factory/resource/branch.rb
+++ b/qa/qa/factory/resource/branch.rb
@@ -2,7 +2,8 @@ module QA
module Factory
module Resource
class Branch < Factory::Base
- attr_accessor :project, :branch_name, :allow_to_push, :protected
+ attr_accessor :project, :branch_name,
+ :allow_to_push, :allow_to_merge, :protected
dependency Factory::Resource::Project, as: :project do |project|
project.name = 'protected-branch-project'
@@ -23,6 +24,7 @@ module QA
def initialize
@branch_name = 'test/branch'
@allow_to_push = true
+ @allow_to_merge = true
@protected = false
end
@@ -65,7 +67,22 @@ module QA
page.allow_no_one_to_push
end
+ if allow_to_merge
+ page.allow_devs_and_masters_to_merge
+ else
+ page.allow_no_one_to_merge
+ end
+
+ page.wait(reload: false) do
+ !page.first('.btn-create').disabled?
+ end
+
page.protect_branch
+
+ # Wait for page load, which resets the expanded sections
+ page.wait(reload: false) do
+ !page.has_content?('Collapse')
+ end
end
end
end
diff --git a/qa/qa/page/project/settings/protected_branches.rb b/qa/qa/page/project/settings/protected_branches.rb
index f3563401124..63bc3aaa2bc 100644
--- a/qa/qa/page/project/settings/protected_branches.rb
+++ b/qa/qa/page/project/settings/protected_branches.rb
@@ -11,6 +11,13 @@ module QA
view 'app/views/projects/protected_branches/_create_protected_branch.html.haml' do
element :allowed_to_push_select
element :allowed_to_push_dropdown
+ element :allowed_to_merge_select
+ element :allowed_to_merge_dropdown
+ end
+
+ view 'app/views/projects/protected_branches/_update_protected_branch.html.haml' do
+ element :allowed_to_push
+ element :allowed_to_merge
end
view 'app/views/projects/protected_branches/shared/_branches_list.html.haml' do
@@ -30,11 +37,19 @@ module QA
end
def allow_no_one_to_push
- allow_to_push('No one')
+ click_allow(:push, 'No one')
end
def allow_devs_and_masters_to_push
- allow_to_push('Developers + Masters')
+ click_allow(:push, 'Developers + Masters')
+ end
+
+ def allow_no_one_to_merge
+ click_allow(:merge, 'No one')
+ end
+
+ def allow_devs_and_masters_to_merge
+ click_allow(:merge, 'Developers + Masters')
end
def protect_branch
@@ -55,11 +70,15 @@ module QA
private
- def allow_to_push(text)
- click_element :allowed_to_push_select
+ def click_allow(action, text)
+ click_element :"allowed_to_#{action}_select"
- within_element(:allowed_to_push_dropdown) do
+ within_element(:"allowed_to_#{action}_dropdown") do
click_on text
+
+ wait(reload: false) do
+ has_css?('.is-active')
+ end
end
end
end
diff --git a/qa/qa/runtime/key/ecdsa.rb b/qa/qa/runtime/key/ecdsa.rb
index 71238e4352a..20adad45913 100644
--- a/qa/qa/runtime/key/ecdsa.rb
+++ b/qa/qa/runtime/key/ecdsa.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Naming/FileName
module QA
module Runtime
module Key
diff --git a/qa/qa/runtime/key/ed25519.rb b/qa/qa/runtime/key/ed25519.rb
index bd2f2522447..63865c1cee5 100644
--- a/qa/qa/runtime/key/ed25519.rb
+++ b/qa/qa/runtime/key/ed25519.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Naming/FileName
module QA
module Runtime
module Key
diff --git a/qa/qa/specs/features/repository/protected_branches_spec.rb b/qa/qa/specs/features/repository/protected_branches_spec.rb
index 89f0e0673af..406b2772b64 100644
--- a/qa/qa/specs/features/repository/protected_branches_spec.rb
+++ b/qa/qa/specs/features/repository/protected_branches_spec.rb
@@ -19,6 +19,13 @@ module QA
Page::Main::Login.act { sign_in_using_credentials }
end
+ after do
+ # We need to clear localStorage because we're using it for the dropdown,
+ # and capybara doesn't do this for us.
+ # https://github.com/teamcapybara/capybara/issues/1702
+ Capybara.execute_script 'localStorage.clear()'
+ end
+
scenario 'user is able to protect a branch' do
protected_branch = Factory::Resource::Branch.fabricate! do |resource|
resource.branch_name = branch_name
diff --git a/spec/features/projects/tree/upload_file_spec.rb b/spec/features/projects/tree/upload_file_spec.rb
index 8e53ae15700..4dfc325b37e 100644
--- a/spec/features/projects/tree/upload_file_spec.rb
+++ b/spec/features/projects/tree/upload_file_spec.rb
@@ -35,17 +35,4 @@ feature 'Multi-file editor upload file', :js do
expect(page).to have_selector('.multi-file-tab', text: 'doc_sample.txt')
expect(find('.blob-editor-container .lines-content')['innerText']).to have_content(File.open(txt_file, &:readline))
end
-
- it 'uploads image file' do
- find('.add-to-tree').click
-
- # make the field visible so capybara can use it
- execute_script('document.querySelector("#file-upload").classList.remove("hidden")')
- attach_file('file-upload', img_file)
-
- find('.add-to-tree').click
-
- expect(page).to have_selector('.multi-file-tab', text: 'dk.png')
- expect(page).not_to have_selector('.monaco-editor')
- end
end
diff --git a/spec/finders/pipelines_finder_spec.rb b/spec/finders/pipelines_finder_spec.rb
index 2b19cda35b0..d6253b605b9 100644
--- a/spec/finders/pipelines_finder_spec.rb
+++ b/spec/finders/pipelines_finder_spec.rb
@@ -203,5 +203,25 @@ describe PipelinesFinder do
end
end
end
+
+ context 'when sha is specified' do
+ let!(:pipeline) { create(:ci_pipeline, project: project, sha: '97de212e80737a608d939f648d959671fb0a0142') }
+
+ context 'when sha exists' do
+ let(:params) { { sha: '97de212e80737a608d939f648d959671fb0a0142' } }
+
+ it 'returns matched pipelines' do
+ is_expected.to eq([pipeline])
+ end
+ end
+
+ context 'when sha does not exist' do
+ let(:params) { { sha: 'invalid-sha' } }
+
+ it 'returns empty' do
+ is_expected.to be_empty
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/pages_client_spec.rb b/spec/lib/gitlab/pages_client_spec.rb
new file mode 100644
index 00000000000..da6d26f4aee
--- /dev/null
+++ b/spec/lib/gitlab/pages_client_spec.rb
@@ -0,0 +1,172 @@
+require 'spec_helper'
+
+describe Gitlab::PagesClient do
+ subject { described_class }
+
+ describe '.token' do
+ it 'returns the token as it is on disk' do
+ pending 'add omnibus support for generating the secret file https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/2466'
+ expect(subject.token).to eq(File.read('.gitlab_pages_secret'))
+ end
+ end
+
+ describe '.read_or_create_token' do
+ subject { described_class.read_or_create_token }
+ let(:token_path) { 'tmp/tests/gitlab-pages-secret' }
+ before do
+ allow(described_class).to receive(:token_path).and_return(token_path)
+ FileUtils.rm_f(token_path)
+ end
+
+ it 'uses the existing token file if it exists' do
+ secret = 'existing secret'
+ File.write(token_path, secret)
+
+ subject
+ expect(described_class.token).to eq(secret)
+ end
+
+ it 'creates one if none exists' do
+ pending 'add omnibus support for generating the secret file https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/2466'
+
+ old_token = described_class.token
+ # sanity check
+ expect(File.exist?(token_path)).to eq(false)
+
+ subject
+ expect(described_class.token.bytesize).to eq(64)
+ expect(described_class.token).not_to eq(old_token)
+ end
+ end
+
+ describe '.write_token' do
+ let(:token_path) { 'tmp/tests/gitlab-pages-secret' }
+ before do
+ allow(described_class).to receive(:token_path).and_return(token_path)
+ FileUtils.rm_f(token_path)
+ end
+
+ it 'writes the secret' do
+ new_secret = 'hello new secret'
+ expect(File.exist?(token_path)).to eq(false)
+
+ described_class.send(:write_token, new_secret)
+
+ expect(File.read(token_path)).to eq(new_secret)
+ end
+
+ it 'does nothing if the file already exists' do
+ existing_secret = 'hello secret'
+ File.write(token_path, existing_secret)
+
+ described_class.send(:write_token, 'new secret')
+
+ expect(File.read(token_path)).to eq(existing_secret)
+ end
+ end
+
+ describe '.load_certificate' do
+ subject { described_class.load_certificate }
+ before do
+ allow(described_class).to receive(:config).and_return(config)
+ end
+
+ context 'with no certificate in the config' do
+ let(:config) { double(:config, certificate: '') }
+
+ it 'does not set @certificate' do
+ subject
+
+ expect(described_class.certificate).to be_nil
+ end
+ end
+
+ context 'with a certificate path in the config' do
+ let(:certificate_path) { 'tmp/tests/fake-certificate' }
+ let(:config) { double(:config, certificate: certificate_path) }
+
+ it 'sets @certificate' do
+ certificate_data = "--- BEGIN CERTIFICATE ---\nbla\n--- END CERTIFICATE ---\n"
+ File.write(certificate_path, certificate_data)
+ subject
+
+ expect(described_class.certificate).to eq(certificate_data)
+ end
+ end
+ end
+
+ describe '.request_kwargs' do
+ let(:token) { 'secret token' }
+ let(:auth_header) { 'Bearer c2VjcmV0IHRva2Vu' }
+ before do
+ allow(described_class).to receive(:token).and_return(token)
+ end
+
+ context 'without timeout' do
+ it { expect(subject.send(:request_kwargs, nil)[:metadata]['authorization']).to eq(auth_header) }
+ end
+
+ context 'with timeout' do
+ let(:timeout) { 1.second }
+
+ it 'still sets the authorization header' do
+ expect(subject.send(:request_kwargs, timeout)[:metadata]['authorization']).to eq(auth_header)
+ end
+
+ it 'sets a deadline value' do
+ now = Time.now
+ deadline = subject.send(:request_kwargs, timeout)[:deadline]
+
+ expect(deadline).to be_between(now, now + 2 * timeout)
+ end
+ end
+ end
+
+ describe '.stub' do
+ before do
+ allow(described_class).to receive(:address).and_return('unix:/foo/bar')
+ end
+
+ it { expect(subject.send(:stub, :health_check)).to be_a(Grpc::Health::V1::Health::Stub) }
+ end
+
+ describe '.address' do
+ subject { described_class.send(:address) }
+
+ before do
+ allow(described_class).to receive(:config).and_return(config)
+ end
+
+ context 'with a unix: address' do
+ let(:config) { double(:config, address: 'unix:/foo/bar') }
+
+ it { expect(subject).to eq('unix:/foo/bar') }
+ end
+
+ context 'with a tcp:// address' do
+ let(:config) { double(:config, address: 'tcp://localhost:1234') }
+
+ it { expect(subject).to eq('localhost:1234') }
+ end
+ end
+
+ describe '.grpc_creds' do
+ subject { described_class.send(:grpc_creds) }
+
+ before do
+ allow(described_class).to receive(:config).and_return(config)
+ end
+
+ context 'with a unix: address' do
+ let(:config) { double(:config, address: 'unix:/foo/bar') }
+
+ it { expect(subject).to eq(:this_channel_is_insecure) }
+ end
+
+ context 'with a tcp:// address' do
+ let(:config) { double(:config, address: 'tcp://localhost:1234') }
+
+ it { expect(subject).to be_a(GRPC::Core::ChannelCredentials) }
+ end
+ end
+end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index e45fe7db1e7..630b9e0519f 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -1224,15 +1224,15 @@ describe Repository do
end
end
- shared_examples 'repo exists check' do
+ describe '#exists?' do
it 'returns true when a repository exists' do
- expect(repository.exists?).to eq(true)
+ expect(repository.exists?).to be(true)
end
it 'returns false if no full path can be constructed' do
allow(repository).to receive(:full_path).and_return(nil)
- expect(repository.exists?).to eq(false)
+ expect(repository.exists?).to be(false)
end
context 'with broken storage', :broken_storage do
@@ -1242,16 +1242,6 @@ describe Repository do
end
end
- describe '#exists?' do
- context 'when repository_exists is disabled' do
- it_behaves_like 'repo exists check'
- end
-
- context 'when repository_exists is enabled', :skip_gitaly_mock do
- it_behaves_like 'repo exists check'
- end
- end
-
describe '#has_visible_content?' do
before do
# If raw_repository.has_visible_content? gets called more than once then
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 893804f1470..e28b0ea5cf2 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -909,13 +909,7 @@ describe SystemNoteService do
it 'sets the note text' do
noteable.update_attribute(:time_estimate, 277200)
- expect(subject.note).to eq "changed time estimate to 1w 4d 5h,"
- end
-
- it 'appends a comma to separate the note from the update_at time' do
- noteable.update_attribute(:time_estimate, 277200)
-
- expect(subject.note).to end_with(',')
+ expect(subject.note).to eq "changed time estimate to 1w 4d 5h"
end
end