diff options
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 |