Commit 26630b9f authored by Phil Hughes's avatar Phil Hughes

Merge branch 'master' into 44846-improve-web-ide-left-panel-and-modes

parents 6a651eb7 87f1736a
...@@ -72,3 +72,4 @@ eslint-report.html ...@@ -72,3 +72,4 @@ eslint-report.html
/locale/**/*.time_stamp /locale/**/*.time_stamp
/.rspec /.rspec
/plugins/* /plugins/*
/.gitlab_pages_secret
...@@ -110,7 +110,7 @@ stages: ...@@ -110,7 +110,7 @@ stages:
# Jobs that only need to pull cache # Jobs that only need to pull cache
.dedicated-no-docs-pull-cache-job: &dedicated-no-docs-pull-cache-job .dedicated-no-docs-pull-cache-job: &dedicated-no-docs-pull-cache-job
<<: *dedicated-runner <<: *dedicated-runner
<<: *except-docs-and-qa <<: *except-docs
<<: *pull-cache <<: *pull-cache
dependencies: dependencies:
- setup-test-env - setup-test-env
...@@ -122,6 +122,10 @@ stages: ...@@ -122,6 +122,10 @@ stages:
variables: variables:
SETUP_DB: "false" 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 .rake-exec: &rake-exec
<<: *dedicated-no-docs-no-db-pull-cache-job <<: *dedicated-no-docs-no-db-pull-cache-job
script: script:
...@@ -222,7 +226,7 @@ stages: ...@@ -222,7 +226,7 @@ stages:
- master@gitlab/gitlab-ee - master@gitlab/gitlab-ee
.gitlab-setup: &gitlab-setup .gitlab-setup: &gitlab-setup
<<: *dedicated-no-docs-pull-cache-job <<: *dedicated-no-docs-and-no-qa-pull-cache-job
<<: *use-pg <<: *use-pg
variables: variables:
CREATE_DB_USER: "true" CREATE_DB_USER: "true"
...@@ -262,12 +266,12 @@ stages: ...@@ -262,12 +266,12 @@ stages:
# DB migration, rollback, and seed jobs # DB migration, rollback, and seed jobs
.db-migrate-reset: &db-migrate-reset .db-migrate-reset: &db-migrate-reset
<<: *dedicated-no-docs-pull-cache-job <<: *dedicated-no-docs-and-no-qa-pull-cache-job
script: script:
- bundle exec rake db:migrate:reset - bundle exec rake db:migrate:reset
.migration-paths: &migration-paths .migration-paths: &migration-paths
<<: *dedicated-no-docs-pull-cache-job <<: *dedicated-no-docs-and-no-qa-pull-cache-job
variables: variables:
CREATE_DB_USER: "true" CREATE_DB_USER: "true"
script: script:
...@@ -647,7 +651,7 @@ migration:path-mysql: ...@@ -647,7 +651,7 @@ migration:path-mysql:
<<: *use-mysql <<: *use-mysql
.db-rollback: &db-rollback .db-rollback: &db-rollback
<<: *dedicated-no-docs-pull-cache-job <<: *dedicated-no-docs-and-no-qa-pull-cache-job
script: script:
- bundle exec rake db:migrate VERSION=20170523121229 - bundle exec rake db:migrate VERSION=20170523121229
- bundle exec rake db:migrate - bundle exec rake db:migrate
...@@ -670,7 +674,7 @@ gitlab:setup-mysql: ...@@ -670,7 +674,7 @@ gitlab:setup-mysql:
# Frontend-related jobs # Frontend-related jobs
gitlab:assets:compile: gitlab:assets:compile:
<<: *dedicated-no-docs-no-db-pull-cache-job <<: *dedicated-no-docs-and-no-qa-pull-cache-job
dependencies: [] dependencies: []
variables: variables:
NODE_ENV: "production" NODE_ENV: "production"
...@@ -691,7 +695,7 @@ gitlab:assets:compile: ...@@ -691,7 +695,7 @@ gitlab:assets:compile:
- webpack-report/ - webpack-report/
karma: karma:
<<: *dedicated-no-docs-pull-cache-job <<: *dedicated-no-docs-and-no-qa-pull-cache-job
<<: *use-pg <<: *use-pg
dependencies: dependencies:
- compile-assets - compile-assets
...@@ -815,7 +819,7 @@ coverage: ...@@ -815,7 +819,7 @@ coverage:
- coverage/assets/ - coverage/assets/
lint:javascript:report: lint:javascript:report:
<<: *dedicated-no-docs-no-db-pull-cache-job <<: *dedicated-no-docs-and-no-qa-pull-cache-job
stage: post-test stage: post-test
dependencies: dependencies:
- compile-assets - compile-assets
......
...@@ -14,6 +14,7 @@ class PipelinesFinder ...@@ -14,6 +14,7 @@ class PipelinesFinder
items = by_scope(items) items = by_scope(items)
items = by_status(items) items = by_status(items)
items = by_ref(items) items = by_ref(items)
items = by_sha(items)
items = by_name(items) items = by_name(items)
items = by_username(items) items = by_username(items)
items = by_yaml_errors(items) items = by_yaml_errors(items)
...@@ -69,6 +70,14 @@ class PipelinesFinder ...@@ -69,6 +70,14 @@ class PipelinesFinder
end end
end end
def by_sha(items)
if params[:sha].present?
items.where(sha: params[:sha])
else
items
end
end
def by_name(items) def by_name(items)
if params[:name].present? if params[:name].present?
items.joins(:user).where(users: { name: params[:name] }) items.joins(:user).where(users: { name: params[:name] })
......
...@@ -159,7 +159,7 @@ module SystemNoteService ...@@ -159,7 +159,7 @@ module SystemNoteService
body = if noteable.time_estimate == 0 body = if noteable.time_estimate == 0
"removed time estimate" "removed time estimate"
else else
"changed time estimate to #{parsed_time}," "changed time estimate to #{parsed_time}"
end end
create_note(NoteSummary.new(noteable, project, author, body, action: 'time_tracking')) create_note(NoteSummary.new(noteable, project, author, body, action: 'time_tracking'))
......
- content_for :merge_access_levels do - content_for :merge_access_levels do
.merge_access_levels-container .merge_access_levels-container
= dropdown_tag('Select', = dropdown_tag('Select',
options: { toggle_class: 'js-allowed-to-merge wide', options: { toggle_class: 'js-allowed-to-merge qa-allowed-to-merge-select wide',
dropdown_class: 'dropdown-menu-selectable capitalize-header', 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' }}) data: { field_name: 'protected_branch[merge_access_levels_attributes][0][access_level]', input_id: 'merge_access_levels_attributes' }})
- content_for :push_access_levels do - content_for :push_access_levels do
.push_access_levels-container .push_access_levels-container
......
%td %td
= hidden_field_tag "allowed_to_merge_#{protected_branch.id}", protected_branch.merge_access_levels.first.access_level = 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') , = 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 }}) data: { field_name: "allowed_to_merge_#{protected_branch.id}", access_level_id: protected_branch.merge_access_levels.first.id }})
%td %td
= hidden_field_tag "allowed_to_push_#{protected_branch.id}", protected_branch.push_access_levels.first.access_level = hidden_field_tag "allowed_to_push_#{protected_branch.id}", protected_branch.push_access_levels.first.access_level
......
...@@ -36,5 +36,6 @@ ...@@ -36,5 +36,6 @@
= form.text_field :domain, class: 'form-control', placeholder: 'domain.com' = form.text_field :domain, class: 'form-control', placeholder: 'domain.com'
.help-block .help-block
= s_('CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages.') = 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" = f.submit 'Save changes', class: "btn btn-success prepend-top-15"
---
title: Add sha filter to pipelines list API
merge_request: 18125
author:
type: changed
---
title: Repository#exists? is always executed through Gitaly
merge_request:
author:
type: performance
...@@ -184,18 +184,18 @@ production: &base ...@@ -184,18 +184,18 @@ production: &base
# base_dir: uploads/-/system # base_dir: uploads/-/system
object_store: object_store:
enabled: false 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) # 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) # 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 # proxy_download: false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage
connection: connection:
provider: AWS provider: AWS
aws_access_key_id: AWS_ACCESS_KEY_ID aws_access_key_id: AWS_ACCESS_KEY_ID
aws_secret_access_key: AWS_SECRET_ACCESS_KEY aws_secret_access_key: AWS_SECRET_ACCESS_KEY
region: us-east-1 region: us-east-1
# host: 'localhost' # default: s3.amazonaws.com # host: 'localhost' # default: s3.amazonaws.com
# endpoint: 'http://127.0.0.1:9000' # default: nil # endpoint: 'http://127.0.0.1:9000' # default: nil
# path_style: true # Use 'host/bucket_name/object' instead of 'bucket_name.host/object' # path_style: true # Use 'host/bucket_name/object' instead of 'bucket_name.host/object'
## GitLab Pages ## GitLab Pages
pages: pages:
...@@ -212,6 +212,8 @@ production: &base ...@@ -212,6 +212,8 @@ production: &base
artifacts_server: true artifacts_server: true
# external_http: ["1.1.1.1:80", "[2001::1]:80"] # If defined, enables custom domain support in GitLab Pages # 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 # 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 ## Mattermost
## For enabling Add to Mattermost button ## For enabling Add to Mattermost button
......
...@@ -215,6 +215,9 @@ Settings.pages['external_http'] ||= false unless Settings.pages['external_ht ...@@ -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['external_https'] ||= false unless Settings.pages['external_https'].present?
Settings.pages['artifacts_server'] ||= Settings.pages['enabled'] if Settings.pages['artifacts_server'].nil? Settings.pages['artifacts_server'] ||= Settings.pages['enabled'] if Settings.pages['artifacts_server'].nil?
Settings.pages['admin'] ||= Settingslogic.new({})
Settings.pages.admin['certificate'] ||= ''
# #
# Git LFS # Git LFS
# #
......
Gitlab::PagesClient.read_or_create_token
Gitlab::PagesClient.load_certificate
...@@ -14,6 +14,7 @@ GET /projects/:id/pipelines ...@@ -14,6 +14,7 @@ GET /projects/:id/pipelines
| `scope` | string | no | The scope of pipelines, one of: `running`, `pending`, `finished`, `branches`, `tags` | | `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` | | `status` | string | no | The status of pipelines, one of: `running`, `pending`, `success`, `failed`, `canceled`, `skipped` |
| `ref` | string | no | The ref of pipelines | | `ref` | string | no | The ref of pipelines |
| `sha` | string | no | The sha or pipelines |
| `yaml_errors`| boolean | no | Returns pipelines with invalid configurations | | `yaml_errors`| boolean | no | Returns pipelines with invalid configurations |
| `name`| string | no | The name of the user who triggered pipelines | | `name`| string | no | The name of the user who triggered pipelines |
| `username`| string | no | The username of the user who triggered pipelines | | `username`| string | no | The username of the user who triggered pipelines |
......
...@@ -135,6 +135,11 @@ and `1.2.3.4` is the IP address of your load balancer; generally NGINX ...@@ -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 ([see prerequisites](#prerequisites)). How to set up the DNS record is beyond
the scope of this document; you should check with your DNS provider. 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 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). them to the Kubernetes pods that run your application(s).
......
...@@ -19,6 +19,7 @@ module API ...@@ -19,6 +19,7 @@ module API
optional :status, type: String, values: HasStatus::AVAILABLE_STATUSES, optional :status, type: String, values: HasStatus::AVAILABLE_STATUSES,
desc: 'The status of pipelines' desc: 'The status of pipelines'
optional :ref, type: String, desc: 'The ref 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 :yaml_errors, type: Boolean, desc: 'Returns pipelines with invalid configurations'
optional :name, type: String, desc: 'The name of the user who triggered pipelines' 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' optional :username, type: String, desc: 'The username of the user who triggered pipelines'
......
...@@ -142,15 +142,7 @@ module Gitlab ...@@ -142,15 +142,7 @@ module Gitlab
end end
def exists? def exists?
Gitlab::GitalyClient.migrate(:repository_exists, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |enabled| gitaly_repository_client.exists?
if enabled
gitaly_repository_client.exists?
else
circuit_breaker.perform do
File.exist?(File.join(path, 'refs'))
end
end
end
end end
# Returns an Array of branch names # Returns an Array of branch names
......
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
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
...@@ -3,7 +3,9 @@ module QA ...@@ -3,7 +3,9 @@ module QA
module Repository module Repository
class Push < Factory::Base class Push < Factory::Base
attr_accessor :file_name, :file_content, :commit_message, 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| dependency Factory::Resource::Project, as: :project do |project|
project.name = 'project-with-code' project.name = 'project-with-code'
......
...@@ -2,7 +2,8 @@ module QA ...@@ -2,7 +2,8 @@ module QA
module Factory module Factory
module Resource module Resource
class Branch < Factory::Base 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| dependency Factory::Resource::Project, as: :project do |project|
project.name = 'protected-branch-project' project.name = 'protected-branch-project'
...@@ -23,6 +24,7 @@ module QA ...@@ -23,6 +24,7 @@ module QA
def initialize def initialize
@branch_name = 'test/branch' @branch_name = 'test/branch'
@allow_to_push = true @allow_to_push = true
@allow_to_merge = true
@protected = false @protected = false
end end
...@@ -65,7 +67,22 @@ module QA ...@@ -65,7 +67,22 @@ module QA
page.allow_no_one_to_push page.allow_no_one_to_push
end 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 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 end
end end
......
...@@ -11,6 +11,13 @@ module QA ...@@ -11,6 +11,13 @@ module QA
view 'app/views/projects/protected_branches/_create_protected_branch.html.haml' do view 'app/views/projects/protected_branches/_create_protected_branch.html.haml' do
element :allowed_to_push_select element :allowed_to_push_select
element :allowed_to_push_dropdown 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 end
view 'app/views/projects/protected_branches/shared/_branches_list.html.haml' do view 'app/views/projects/protected_branches/shared/_branches_list.html.haml' do
...@@ -30,11 +37,19 @@ module QA ...@@ -30,11 +37,19 @@ module QA
end end
def allow_no_one_to_push def allow_no_one_to_push
allow_to_push('No one') click_allow(:push, 'No one')
end end
def allow_devs_and_masters_to_push 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 end
def protect_branch def protect_branch
...@@ -55,11 +70,15 @@ module QA ...@@ -55,11 +70,15 @@ module QA
private private
def allow_to_push(text) def click_allow(action, text)
click_element :allowed_to_push_select click_element :"allowed_to_#{action}_select"
within_element(:allowed_to_push_dropdown) do within_element(:"allowed_to_#{action}_dropdown") do
click_on text click_on text
wait(reload: false) do
has_css?('.is-active')
end
end end
end end
end end
......
# rubocop:disable Naming/FileName
module QA module QA
module Runtime module Runtime
module Key module Key
......
# rubocop:disable Naming/FileName
module QA module QA
module Runtime module Runtime
module Key module Key
......
...@@ -19,6 +19,13 @@ module QA ...@@ -19,6 +19,13 @@ module QA
Page::Main::Login.act { sign_in_using_credentials } Page::Main::Login.act { sign_in_using_credentials }
end 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 scenario 'user is able to protect a branch' do
protected_branch = Factory::Resource::Branch.fabricate! do |resource| protected_branch = Factory::Resource::Branch.fabricate! do |resource|
resource.branch_name = branch_name resource.branch_name = branch_name
......
...@@ -35,17 +35,4 @@ feature 'Multi-file editor upload file', :js do ...@@ -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(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)) expect(find('.blob-editor-container .lines-content')['innerText']).to have_content(File.open(txt_file, &:readline))
end 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 end
...@@ -203,5 +203,25 @@ describe PipelinesFinder do ...@@ -203,5 +203,25 @@ describe PipelinesFinder do
end end
end 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
end end
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
...@@ -1224,15 +1224,15 @@ describe Repository do ...@@ -1224,15 +1224,15 @@ describe Repository do
end end
end end
shared_examples 'repo exists check' do describe '#exists?' do
it 'returns true when a repository exists' do it 'returns true when a repository exists' do
expect(repository.exists?).to eq(true) expect(repository.exists?).to be(true)
end end
it 'returns false if no full path can be constructed' do it 'returns false if no full path can be constructed' do
allow(repository).to receive(:full_path).and_return(nil) allow(repository).to receive(:full_path).and_return(nil)
expect(repository.exists?).to eq(false) expect(repository.exists?).to be(false)
end end
context 'with broken storage', :broken_storage do context 'with broken storage', :broken_storage do
...@@ -1242,16 +1242,6 @@ describe Repository do ...@@ -1242,16 +1242,6 @@ describe Repository do
end end
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 describe '#has_visible_content?' do
before do before do
# If raw_repository.has_visible_content? gets called more than once then # If raw_repository.has_visible_content? gets called more than once then
......
...@@ -909,13 +909,7 @@ describe SystemNoteService do ...@@ -909,13 +909,7 @@ describe SystemNoteService do
it 'sets the note text' do it 'sets the note text' do
noteable.update_attribute(:time_estimate, 277200) noteable.update_attribute(:time_estimate, 277200)
expect(subject.note).to eq "changed time estimate to 1w 4d 5h," 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(',')
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment