diff options
21 files changed, 69 insertions, 32 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f9c5ebe7a35..bb1c84ab918 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,7 +6,7 @@ image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.6-golang-1.9-git - gitlab-org .default-cache: &default-cache - key: "ruby-235-with-yarn" + key: "ruby-2.3.6-with-yarn" paths: - vendor/ruby - .yarn-cache/ diff --git a/app/assets/javascripts/behaviors/copy_as_gfm.js b/app/assets/javascripts/behaviors/copy_as_gfm.js index c6eca72c51b..ffe90595b5d 100644 --- a/app/assets/javascripts/behaviors/copy_as_gfm.js +++ b/app/assets/javascripts/behaviors/copy_as_gfm.js @@ -299,6 +299,13 @@ const gfmRules = { export class CopyAsGFM { constructor() { + // iOS currently does not support clipboardData.setData(). This bug should + // be fixed in iOS 12, but for now we'll disable this for all iOS browsers + // ref: https://trac.webkit.org/changeset/222228/webkit + const userAgent = (typeof navigator !== 'undefined' && navigator.userAgent) || ''; + const isIOS = /\b(iPad|iPhone|iPod)(?=;)/.test(userAgent); + if (isIOS) return; + $(document).on('copy', '.md, .wiki', (e) => { CopyAsGFM.copyAsGFM(e, CopyAsGFM.transformGFMSelection); }); $(document).on('copy', 'pre.code.highlight, .diff-content .line_content', (e) => { CopyAsGFM.copyAsGFM(e, CopyAsGFM.transformCodeSelection); }); $(document).on('paste', '.js-gfm-input', CopyAsGFM.pasteGFM); diff --git a/app/assets/javascripts/deploy_keys/components/app.vue b/app/assets/javascripts/deploy_keys/components/app.vue index 7b68b19de75..5a782237b7d 100644 --- a/app/assets/javascripts/deploy_keys/components/app.vue +++ b/app/assets/javascripts/deploy_keys/components/app.vue @@ -87,6 +87,7 @@ <div v-else-if="hasKeys"> <keys-panel title="Enabled deploy keys for this project" + class="qa-project-deploy-keys" :keys="keys.enabled_keys" :store="store" :endpoint="endpoint" diff --git a/changelogs/unreleased/32546-cannot-copy-paste-on-ios.yml b/changelogs/unreleased/32546-cannot-copy-paste-on-ios.yml new file mode 100644 index 00000000000..f4c44983736 --- /dev/null +++ b/changelogs/unreleased/32546-cannot-copy-paste-on-ios.yml @@ -0,0 +1,5 @@ +--- +title: Fix copy/paste on iOS devices due to a bug in webkit +merge_request: 15804 +author: +type: fixed diff --git a/doc/development/fe_guide/axios.md b/doc/development/fe_guide/axios.md index dcd8f5cb839..0d9397c3bd5 100644 --- a/doc/development/fe_guide/axios.md +++ b/doc/development/fe_guide/axios.md @@ -63,7 +63,7 @@ We have also decided against using [axios interceptors] because they are not sui }); afterEach(() => { - mock.reset(); + mock.restore(); }); ``` diff --git a/lib/gitlab/gitaly_client/conflicts_service.rb b/lib/gitlab/gitaly_client/conflicts_service.rb index 2565d537aff..e14734495a8 100644 --- a/lib/gitlab/gitaly_client/conflicts_service.rb +++ b/lib/gitlab/gitaly_client/conflicts_service.rb @@ -25,6 +25,11 @@ module Gitlab def conflicts? list_conflict_files.any? + rescue GRPC::FailedPrecondition + # The server raises this exception when it encounters ConflictSideMissing, which + # means a conflict exists but its `theirs` or `ours` data is nil due to a non-existent + # file in one of the trees. + true end def resolve_conflicts(target_repository, resolution, source_branch, target_branch) diff --git a/qa/qa/factory/resource/deploy_key.rb b/qa/qa/factory/resource/deploy_key.rb index 7c58e70bcc4..671114d38b1 100644 --- a/qa/qa/factory/resource/deploy_key.rb +++ b/qa/qa/factory/resource/deploy_key.rb @@ -4,6 +4,12 @@ module QA class DeployKey < Factory::Base attr_accessor :title, :key + product :title do + Page::Project::Settings::Repository.act do + expand_deploy_keys(&:key_title) + end + end + dependency Factory::Resource::Project, as: :project do |project| project.name = 'project-to-deploy' project.description = 'project for adding deploy key test' diff --git a/qa/qa/page/project/settings/deploy_keys.rb b/qa/qa/page/project/settings/deploy_keys.rb index bf42767c707..f9e40bf4252 100644 --- a/qa/qa/page/project/settings/deploy_keys.rb +++ b/qa/qa/page/project/settings/deploy_keys.rb @@ -10,6 +10,7 @@ module QA view 'app/assets/javascripts/deploy_keys/components/app.vue' do element :deploy_keys_section, /class=".*deploy\-keys.*"/ + element :project_deploy_keys, 'class="qa-project-deploy-keys"' end view 'app/assets/javascripts/deploy_keys/components/key.vue' do @@ -29,9 +30,9 @@ module QA click_on 'Add key' end - def has_key_title?(title) - page.within('.deploy-keys') do - page.find('.title', text: title) + def key_title + page.within('.qa-project-deploy-keys') do + page.find('.title').text end end end diff --git a/qa/qa/specs/features/project/add_deploy_key_spec.rb b/qa/qa/specs/features/project/add_deploy_key_spec.rb index 43a85213501..7a123e539e1 100644 --- a/qa/qa/specs/features/project/add_deploy_key_spec.rb +++ b/qa/qa/specs/features/project/add_deploy_key_spec.rb @@ -7,16 +7,12 @@ module QA Runtime::Browser.visit(:gitlab, Page::Main::Login) Page::Main::Login.act { sign_in_using_credentials } - Factory::Resource::DeployKey.fabricate! do |deploy_key| - deploy_key.title = deploy_key_title - deploy_key.key = deploy_key_value + deploy_key = Factory::Resource::DeployKey.fabricate! do |resource| + resource.title = deploy_key_title + resource.key = deploy_key_value end - Page::Project::Settings::Repository.perform do |setting| - setting.expand_deploy_keys do |page| - expect(page).to have_key_title(deploy_key_title) - end - end + expect(deploy_key.title).to eq(deploy_key_title) end end end diff --git a/scripts/gitaly-test-build b/scripts/gitaly-test-build index 95d9fe0f176..b42ae2a2595 100755 --- a/scripts/gitaly-test-build +++ b/scripts/gitaly-test-build @@ -9,11 +9,21 @@ require 'fileutils' # called 'bundle install' using a different Gemfile, as happens with # gitlab-ce and gitaly. -dir = 'tmp/tests/gitaly' +tmp_tests_gitaly_dir = File.expand_path('../tmp/tests/gitaly', __dir__) -abort 'gitaly build failed' unless system('make', chdir: dir) +# Use the top-level bundle vendor folder so that we don't reinstall gems twice +bundle_vendor_path = File.expand_path('../vendor', __dir__) + +env = { + # This ensure the `clean` config set in `scripts/prepare_build.sh` isn't taken into account + 'BUNDLE_IGNORE_CONFIG' => 'true', + 'BUNDLE_GEMFILE' => File.join(tmp_tests_gitaly_dir, 'ruby', 'Gemfile'), + 'BUNDLE_FLAGS' => "--jobs=4 --path=#{bundle_vendor_path} --retry=3" +} + +abort 'gitaly build failed' unless system(env, 'make', chdir: tmp_tests_gitaly_dir) # Make the 'gitaly' executable look newer than 'GITALY_SERVER_VERSION'. # Without this a gitaly executable created in the setup-test-env job # will look stale compared to GITALY_SERVER_VERSION. -FileUtils.touch(File.join(dir, 'gitaly'), mtime: Time.now + (1 << 24)) +FileUtils.touch(File.join(tmp_tests_gitaly_dir, 'gitaly'), mtime: Time.now + (1 << 24)) diff --git a/scripts/prepare_build.sh b/scripts/prepare_build.sh index ea406aadf39..206d62dbc78 100644 --- a/scripts/prepare_build.sh +++ b/scripts/prepare_build.sh @@ -3,7 +3,7 @@ export SETUP_DB=${SETUP_DB:-true} export CREATE_DB_USER=${CREATE_DB_USER:-$SETUP_DB} export USE_BUNDLE_INSTALL=${USE_BUNDLE_INSTALL:-true} -export BUNDLE_INSTALL_FLAGS="--without production --jobs $(nproc) --path vendor --retry 3 --quiet" +export BUNDLE_INSTALL_FLAGS="--without=production --jobs=$(nproc) --path=vendor --retry=3 --quiet" if [ "$USE_BUNDLE_INSTALL" != "false" ]; then bundle install --clean $BUNDLE_INSTALL_FLAGS && bundle check diff --git a/spec/javascripts/blob/notebook/index_spec.js b/spec/javascripts/blob/notebook/index_spec.js index df1b2c9960b..a143fc827d5 100644 --- a/spec/javascripts/blob/notebook/index_spec.js +++ b/spec/javascripts/blob/notebook/index_spec.js @@ -45,7 +45,7 @@ describe('iPython notebook renderer', () => { }); afterEach(() => { - mock.reset(); + mock.restore(); }); it('does not show loading icon', () => { @@ -96,7 +96,7 @@ describe('iPython notebook renderer', () => { }); afterEach(() => { - mock.reset(); + mock.restore(); }); it('does not show loading icon', () => { @@ -127,7 +127,7 @@ describe('iPython notebook renderer', () => { }); afterEach(() => { - mock.reset(); + mock.restore(); }); it('does not show loading icon', () => { diff --git a/spec/javascripts/boards/board_card_spec.js b/spec/javascripts/boards/board_card_spec.js index 4e73fa1fe87..80a598e63bd 100644 --- a/spec/javascripts/boards/board_card_spec.js +++ b/spec/javascripts/boards/board_card_spec.js @@ -55,7 +55,7 @@ describe('Board card', () => { }); afterEach(() => { - mock.reset(); + mock.restore(); }); it('returns false when detailIssue is empty', () => { diff --git a/spec/javascripts/boards/board_list_spec.js b/spec/javascripts/boards/board_list_spec.js index 9ffdac9be97..a5fcb10b9dd 100644 --- a/spec/javascripts/boards/board_list_spec.js +++ b/spec/javascripts/boards/board_list_spec.js @@ -60,7 +60,7 @@ describe('Board list component', () => { }); afterEach(() => { - mock.reset(); + mock.restore(); }); it('renders component', () => { diff --git a/spec/javascripts/boards/board_new_issue_spec.js b/spec/javascripts/boards/board_new_issue_spec.js index c62c537841c..e204985f039 100644 --- a/spec/javascripts/boards/board_new_issue_spec.js +++ b/spec/javascripts/boards/board_new_issue_spec.js @@ -58,7 +58,7 @@ describe('Issue boards new issue form', () => { afterEach(() => { vm.$destroy(); - mock.reset(); + mock.restore(); }); it('calls submit if submit button is clicked', (done) => { diff --git a/spec/javascripts/boards/boards_store_spec.js b/spec/javascripts/boards/boards_store_spec.js index 49fb20f4c84..8411f4dd8a6 100644 --- a/spec/javascripts/boards/boards_store_spec.js +++ b/spec/javascripts/boards/boards_store_spec.js @@ -35,7 +35,7 @@ describe('Store', () => { }); afterEach(() => { - mock.reset(); + mock.restore(); }); it('starts with a blank state', () => { diff --git a/spec/javascripts/boards/list_spec.js b/spec/javascripts/boards/list_spec.js index e5e7b48228b..34964b20b05 100644 --- a/spec/javascripts/boards/list_spec.js +++ b/spec/javascripts/boards/list_spec.js @@ -30,7 +30,7 @@ describe('List model', () => { }); afterEach(() => { - mock.reset(); + mock.restore(); }); it('gets issues when created', (done) => { diff --git a/spec/javascripts/issue_show/components/app_spec.js b/spec/javascripts/issue_show/components/app_spec.js index 9280db072b3..1c9f48028f2 100644 --- a/spec/javascripts/issue_show/components/app_spec.js +++ b/spec/javascripts/issue_show/components/app_spec.js @@ -59,7 +59,7 @@ describe('Issuable output', () => { }); afterEach(() => { - mock.reset(); + mock.restore(); realtimeRequestCount = 0; vm.poll.stop(); diff --git a/spec/javascripts/jobs/job_details_mediator_spec.js b/spec/javascripts/jobs/job_details_mediator_spec.js index 3069a0cd60e..ca5c9cf87e4 100644 --- a/spec/javascripts/jobs/job_details_mediator_spec.js +++ b/spec/javascripts/jobs/job_details_mediator_spec.js @@ -12,6 +12,10 @@ describe('JobMediator', () => { mock = new MockAdapter(axios); }); + afterEach(() => { + mock.restore(); + }); + it('should set defaults', () => { expect(mediator.store).toBeDefined(); expect(mediator.service).toBeDefined(); @@ -24,10 +28,6 @@ describe('JobMediator', () => { mock.onGet().reply(200, job, {}); }); - afterEach(() => { - mock.restore(); - }); - it('should store received data', (done) => { mediator.fetchJob(); setTimeout(() => { diff --git a/spec/javascripts/monitoring/dashboard_spec.js b/spec/javascripts/monitoring/dashboard_spec.js index 9885b8a790f..eb8f6bbe50d 100644 --- a/spec/javascripts/monitoring/dashboard_spec.js +++ b/spec/javascripts/monitoring/dashboard_spec.js @@ -38,7 +38,7 @@ describe('Dashboard', () => { }); afterEach(() => { - mock.reset(); + mock.restore(); }); it('shows up a loading state', (done) => { diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index baaa9e3ef44..8f406253f39 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -365,12 +365,18 @@ describe Repository do it { is_expected.to be_truthy } end - context 'non-mergeable branches' do + context 'non-mergeable branches without conflict sides missing' do subject { repository.can_be_merged?('bb5206fee213d983da88c47f9cf4cc6caf9c66dc', 'feature') } it { is_expected.to be_falsey } end + context 'non-mergeable branches with conflict sides missing' do + subject { repository.can_be_merged?('conflict-missing-side', 'conflict-start') } + + it { is_expected.to be_falsey } + end + context 'non merged branch' do subject { repository.merged_to_root_ref?('fix') } |