From d00d60a66deeacb19ccbd39501946ed646db64b6 Mon Sep 17 00:00:00 2001 From: Ash McKenzie Date: Tue, 16 Jul 2019 14:20:52 +1000 Subject: Allow UsageData.count to use count_by: --- lib/gitlab/usage_data.rb | 4 ++-- spec/lib/gitlab/usage_data_spec.rb | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb index 7572c0bdbfd..f02d9f7d7e7 100644 --- a/lib/gitlab/usage_data.rb +++ b/lib/gitlab/usage_data.rb @@ -176,8 +176,8 @@ module Gitlab {} # augmented in EE end - def count(relation, fallback: -1) - relation.count + def count(relation, count_by: nil, fallback: -1) + count_by ? relation.count(count_by) : relation.count rescue ActiveRecord::StatementInvalid fallback end diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb index 90a534de202..7fe60fd214c 100644 --- a/spec/lib/gitlab/usage_data_spec.rb +++ b/spec/lib/gitlab/usage_data_spec.rb @@ -234,6 +234,12 @@ describe Gitlab::UsageData do expect(described_class.count(relation)).to eq(1) end + it 'returns the count for count_by when provided' do + allow(relation).to receive(:count).with(:creator_id).and_return(2) + + expect(described_class.count(relation, count_by: :creator_id)).to eq(2) + end + it 'returns the fallback value when counting fails' do allow(relation).to receive(:count).and_raise(ActiveRecord::StatementInvalid.new('')) -- cgit v1.2.1 From f53112de5931144ac74819f87c227f06e115ba58 Mon Sep 17 00:00:00 2001 From: Ash McKenzie Date: Thu, 18 Jul 2019 12:09:30 +1000 Subject: New GroupMember.of_ldap_type scope --- app/models/members/group_member.rb | 2 +- spec/factories/group_members.rb | 4 ++++ spec/models/members/group_member_spec.rb | 36 ++++++++++++++++++++------------ 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb index 4cba69069bb..341d2fe2149 100644 --- a/app/models/members/group_member.rb +++ b/app/models/members/group_member.rb @@ -13,8 +13,8 @@ class GroupMember < Member default_scope { where(source_type: SOURCE_TYPE) } scope :of_groups, ->(groups) { where(source_id: groups.select(:id)) } - scope :count_users_by_group_id, -> { joins(:user).group(:source_id).count } + scope :of_ldap_type, -> { where(ldap: true) } after_create :update_two_factor_requirement, unless: :invite? after_destroy :update_two_factor_requirement, unless: :invite? diff --git a/spec/factories/group_members.rb b/spec/factories/group_members.rb index 077c6ddc5ae..0cf99a31d20 100644 --- a/spec/factories/group_members.rb +++ b/spec/factories/group_members.rb @@ -16,5 +16,9 @@ FactoryBot.define do invite_token 'xxx' invite_email 'email@email.com' end + + trait(:ldap) do + ldap true + end end end diff --git a/spec/models/members/group_member_spec.rb b/spec/models/members/group_member_spec.rb index f227abd3dae..a6928ec31f4 100644 --- a/spec/models/members/group_member_spec.rb +++ b/spec/models/members/group_member_spec.rb @@ -3,19 +3,29 @@ require 'spec_helper' describe GroupMember do - describe '.count_users_by_group_id' do - it 'counts users by group ID' do - user_1 = create(:user) - user_2 = create(:user) - group_1 = create(:group) - group_2 = create(:group) - - group_1.add_owner(user_1) - group_1.add_owner(user_2) - group_2.add_owner(user_1) - - expect(described_class.count_users_by_group_id).to eq(group_1.id => 2, - group_2.id => 1) + context 'scopes' do + describe '.count_users_by_group_id' do + it 'counts users by group ID' do + user_1 = create(:user) + user_2 = create(:user) + group_1 = create(:group) + group_2 = create(:group) + + group_1.add_owner(user_1) + group_1.add_owner(user_2) + group_2.add_owner(user_1) + + expect(described_class.count_users_by_group_id).to eq(group_1.id => 2, + group_2.id => 1) + end + end + + describe '.of_ldap_type' do + it 'returns ldap type users' do + group_member = create(:group_member, :ldap) + + expect(described_class.of_ldap_type).to eq([group_member]) + end end end -- cgit v1.2.1 From 16084ee9d3fdfc333a113e4cbcd3f6d2fc402628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Wed, 31 Jul 2019 17:36:57 +0200 Subject: Port changes from EE Ports changes from https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/12343 --- app/models/ci/pipeline.rb | 4 ++++ doc/ci/multi_project_pipelines.md | 15 +++++++++++++++ lib/gitlab/ci/pipeline/seed/build.rb | 5 ++++- lib/gitlab/ci/yaml_processor.rb | 3 ++- spec/factories/ci/bridge.rb | 9 ++++++++- spec/lib/gitlab/ci/pipeline/seed/build_spec.rb | 24 ++++++++++++++++++++---- spec/lib/gitlab/ci/yaml_processor_spec.rb | 5 ++++- spec/models/ci/bridge_spec.rb | 2 +- spec/models/ci/pipeline_spec.rb | 7 +++++++ 9 files changed, 65 insertions(+), 9 deletions(-) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index ffab4e82f90..754c7a5985f 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -328,6 +328,10 @@ module Ci config_sources.values_at(:repository_source, :auto_devops_source, :unknown_source) end + def self.bridgeable_statuses + ::Ci::Pipeline::AVAILABLE_STATUSES - %w[created preparing pending] + end + def stages_count statuses.select(:stage).distinct.count end diff --git a/doc/ci/multi_project_pipelines.md b/doc/ci/multi_project_pipelines.md index ced4344a0b0..cb8d383f7d9 100644 --- a/doc/ci/multi_project_pipelines.md +++ b/doc/ci/multi_project_pipelines.md @@ -176,6 +176,21 @@ Upstream pipelines take precedence over downstream ones. If there are two variables with the same name defined in both upstream and downstream projects, the ones defined in the upstream project will take precedence. +### Mirroring status from upstream pipeline + +You can mirror the pipeline status from an upstream pipeline to a bridge job by +using the `needs:pipeline` keyword. The latest pipeline status from master is +replicated to the bridge job. + +Example: + +```yaml +upstream_bridge: + stage: test + needs: + pipeline: other/project +``` + ### Limitations Because bridge jobs are a little different to regular jobs, it is not diff --git a/lib/gitlab/ci/pipeline/seed/build.rb b/lib/gitlab/ci/pipeline/seed/build.rb index ab0d4c38ab6..175f146c5b3 100644 --- a/lib/gitlab/ci/pipeline/seed/build.rb +++ b/lib/gitlab/ci/pipeline/seed/build.rb @@ -45,7 +45,10 @@ module Gitlab end def bridge? - @attributes.to_h.dig(:options, :trigger).present? + attributes_hash = @attributes.to_h + attributes_hash.dig(:options, :trigger).present? || + (attributes_hash.dig(:options, :bridge_needs).instance_of?(Hash) && + attributes_hash.dig(:options, :bridge_needs, :pipeline).present?) end def all_of_only? diff --git a/lib/gitlab/ci/yaml_processor.rb b/lib/gitlab/ci/yaml_processor.rb index 998130e5bd0..2e1eab270ff 100644 --- a/lib/gitlab/ci/yaml_processor.rb +++ b/lib/gitlab/ci/yaml_processor.rb @@ -55,7 +55,8 @@ module Gitlab parallel: job[:parallel], instance: job[:instance], start_in: job[:start_in], - trigger: job[:trigger] + trigger: job[:trigger], + bridge_needs: job[:needs] }.compact }.compact end diff --git a/spec/factories/ci/bridge.rb b/spec/factories/ci/bridge.rb index 6491b9dca19..b1b714277e4 100644 --- a/spec/factories/ci/bridge.rb +++ b/spec/factories/ci/bridge.rb @@ -8,7 +8,7 @@ FactoryBot.define do ref 'master' tag false created_at 'Di 29. Okt 09:50:00 CET 2013' - status :success + status :created pipeline factory: :ci_pipeline @@ -17,6 +17,7 @@ FactoryBot.define do end transient { downstream nil } + transient { upstream nil } after(:build) do |bridge, evaluator| bridge.project ||= bridge.pipeline.project @@ -26,6 +27,12 @@ FactoryBot.define do trigger: { project: evaluator.downstream.full_path } ) end + + if evaluator.upstream.present? + bridge.options = bridge.options.to_h.merge( + bridge_needs: { pipeline: evaluator.upstream.full_path } + ) + end end end end diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb index 762025f9bd9..1b8e86b1f18 100644 --- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb @@ -20,20 +20,36 @@ describe Gitlab::Ci::Pipeline::Seed::Build do describe '#bridge?' do subject { seed_build.bridge? } - context 'when job is a bridge' do + context 'when job is a downstream bridge' do let(:attributes) do { name: 'rspec', ref: 'master', options: { trigger: 'my/project' } } end it { is_expected.to be_truthy } + + context 'when trigger definition is empty' do + let(:attributes) do + { name: 'rspec', ref: 'master', options: { trigger: '' } } + end + + it { is_expected.to be_falsey } + end end - context 'when trigger definition is empty' do + context 'when job is an upstream bridge' do let(:attributes) do - { name: 'rspec', ref: 'master', options: { trigger: '' } } + { name: 'rspec', ref: 'master', options: { bridge_needs: { pipeline: 'my/project' } } } end - it { is_expected.to be_falsey } + it { is_expected.to be_truthy } + + context 'when upstream definition is empty' do + let(:attributes) do + { name: 'rspec', ref: 'master', options: { bridge_needs: { pipeline: '' } } } + end + + it { is_expected.to be_falsey } + end end context 'when job is not a bridge' do diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb index 4ffa1fc9fd8..d5567b4f166 100644 --- a/spec/lib/gitlab/ci/yaml_processor_spec.rb +++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb @@ -1153,7 +1153,10 @@ module Gitlab stage_idx: 1, name: "test1", options: { - script: ["test"] + script: ["test"], + # This does not make sense, there is a follow-up: + # https://gitlab.com/gitlab-org/gitlab-ce/issues/65569 + bridge_needs: %w[build1 build2] }, needs_attributes: [ { name: "build1" }, diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb index eb32198265b..a871f9b3fe6 100644 --- a/spec/models/ci/bridge_spec.rb +++ b/spec/models/ci/bridge_spec.rb @@ -23,7 +23,7 @@ describe Ci::Bridge do let(:status) { bridge.detailed_status(user) } it 'returns detailed status object' do - expect(status).to be_a Gitlab::Ci::Status::Success + expect(status).to be_a Gitlab::Ci::Status::Created end end diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 1fb83fbb088..78be4a8131a 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -1929,6 +1929,13 @@ describe Ci::Pipeline, :mailer do it { is_expected.to be_an(Array) } end + describe '.bridgeable_statuses' do + subject { described_class.bridgeable_statuses } + + it { is_expected.to be_an(Array) } + it { is_expected.not_to include('created', 'preparing', 'pending') } + end + describe '#status' do let(:build) do create(:ci_build, :created, pipeline: pipeline, name: 'test') -- cgit v1.2.1 From 7dd545b130cb0cc2196ac15d7968736f679e8072 Mon Sep 17 00:00:00 2001 From: Elliot Rushton Date: Thu, 8 Aug 2019 01:00:23 +0000 Subject: Fix required runner permissions --- doc/ci/runners/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md index 03a219e03ca..f5f8e04755e 100644 --- a/doc/ci/runners/README.md +++ b/doc/ci/runners/README.md @@ -88,7 +88,7 @@ visit the project you want to make the Runner work for in GitLab: ## Registering a group Runner -Creating a group Runner requires Maintainer permissions for the group. To create a +Creating a group Runner requires Owner permissions for the group. To create a group Runner visit the group you want to make the Runner work for in GitLab: 1. Go to **Settings > CI/CD** to obtain the token @@ -124,9 +124,9 @@ To lock/unlock a Runner: ## Assigning a Runner to another project -If you are Maintainer on a project where a specific Runner is assigned to, and the +If you are an Owner on a project where a specific Runner is assigned to, and the Runner is not [locked only to that project](#locking-a-specific-runner-from-being-enabled-for-other-projects), -you can enable the Runner also on any other project where you have Maintainer permissions. +you can enable the Runner also on any other project where you have Owner permissions. To enable/disable a Runner in your project: @@ -250,7 +250,7 @@ When you [register a Runner][register], its default behavior is to **only pick** [tagged jobs](../yaml/README.md#tags). NOTE: **Note:** -Maintainer [permissions](../../user/permissions.md) are required to change the +Owner [permissions](../../user/permissions.md) are required to change the Runner settings. To make a Runner pick untagged jobs: -- cgit v1.2.1 From 7ee68572d33a1fee853a269fa5e2099fe10903c9 Mon Sep 17 00:00:00 2001 From: Alex Buijs Date: Mon, 29 Jul 2019 18:43:43 +0200 Subject: Set cursor to default for warning flash Since the warning flash is not clickable, set the cursor to default --- app/assets/stylesheets/framework/flash.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/app/assets/stylesheets/framework/flash.scss b/app/assets/stylesheets/framework/flash.scss index e3dd127366d..96f6d02a68f 100644 --- a/app/assets/stylesheets/framework/flash.scss +++ b/app/assets/stylesheets/framework/flash.scss @@ -43,6 +43,7 @@ @extend .alert; background-color: $orange-100; color: $orange-900; + cursor: default; margin: 0; } -- cgit v1.2.1 From 2bc0f0cfcf7b201df2e55afb5c1360f3d591782a Mon Sep 17 00:00:00 2001 From: Alex Buijs Date: Wed, 31 Jul 2019 16:47:58 +0200 Subject: Add ConfirmEmailWarning concern --- app/controllers/application_controller.rb | 1 + app/controllers/concerns/confirm_email_warning.rb | 25 ++++++ .../concerns/confirm_email_warning_spec.rb | 98 ++++++++++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 app/controllers/concerns/confirm_email_warning.rb create mode 100644 spec/controllers/concerns/confirm_email_warning_spec.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1d55a073f3b..1268972fbc1 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -12,6 +12,7 @@ class ApplicationController < ActionController::Base include EnforcesTwoFactorAuthentication include WithPerformanceBar include SessionlessAuthentication + include ConfirmEmailWarning before_action :authenticate_user! before_action :enforce_terms!, if: :should_enforce_terms? diff --git a/app/controllers/concerns/confirm_email_warning.rb b/app/controllers/concerns/confirm_email_warning.rb new file mode 100644 index 00000000000..8e2d08c9193 --- /dev/null +++ b/app/controllers/concerns/confirm_email_warning.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module ConfirmEmailWarning + extend ActiveSupport::Concern + + included do + before_action :set_confirm_warning, if: -> { Feature.enabled?(:soft_email_confirmation) } + end + + protected + + def set_confirm_warning + return if peek_request? || json_request? || !request.get? + return unless current_user + return if current_user.confirmed? + + email = current_user.unconfirmed_email || current_user.email + + flash.now[:warning] = _("Please check your email (%{email}) to verify that you own this address. Didn't receive it? %{resend_link}. Wrong email address? %{update_link}.").html_safe % { + email: email, + resend_link: view_context.link_to(_('Resend it'), user_confirmation_path(user: { email: email }), method: :post), + update_link: view_context.link_to(_('Update it'), profile_path) + } + end +end diff --git a/spec/controllers/concerns/confirm_email_warning_spec.rb b/spec/controllers/concerns/confirm_email_warning_spec.rb new file mode 100644 index 00000000000..0c598a360af --- /dev/null +++ b/spec/controllers/concerns/confirm_email_warning_spec.rb @@ -0,0 +1,98 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe ConfirmEmailWarning do + before do + stub_feature_flags(soft_email_confirmation: true) + allow(User).to receive(:allow_unconfirmed_access_for).and_return 2.days + end + + controller(ApplicationController) do + # `described_class` is not available in this context + include ConfirmEmailWarning # rubocop:disable RSpec/DescribedClass + + def index + head :ok + end + end + + RSpec::Matchers.define :set_confirm_warning_for do |email| + match do |response| + expect(response).to set_flash.now[:warning].to include("Please check your email (#{email}) to verify that you own this address.") + end + end + + describe 'confirm email flash warning' do + context 'when not signed in' do + let(:user) { create(:user, confirmed_at: nil) } + + before do + get :index + end + + it { is_expected.not_to set_confirm_warning_for(user.email) } + end + + context 'when signed in' do + before do + sign_in(user) + end + + context 'with a confirmed user' do + let(:user) { create(:user) } + + before do + get :index + end + + it { is_expected.not_to set_confirm_warning_for(user.email) } + end + + context 'with an unconfirmed user' do + let(:user) { create(:user, confirmed_at: nil) } + + context 'when executing a peek request' do + before do + request.path = '/-/peek' + get :index + end + + it { is_expected.not_to set_confirm_warning_for(user.email) } + end + + context 'when executing a json request' do + before do + get :index, format: :json + end + + it { is_expected.not_to set_confirm_warning_for(user.email) } + end + + context 'when executing a post request' do + before do + post :index + end + + it { is_expected.not_to set_confirm_warning_for(user.email) } + end + + context 'when executing a get request' do + before do + get :index + end + + context 'with an unconfirmed email address present' do + let(:user) { create(:user, confirmed_at: nil, unconfirmed_email: 'unconfirmed@gitlab.com') } + + it { is_expected.to set_confirm_warning_for(user.unconfirmed_email) } + end + + context 'without an unconfirmed email address present' do + it { is_expected.to set_confirm_warning_for(user.email) } + end + end + end + end + end +end -- cgit v1.2.1 From 5cbe16c3d2a3a3667021fb8c81f743308aefbdae Mon Sep 17 00:00:00 2001 From: Alex Buijs Date: Wed, 31 Jul 2019 16:48:38 +0200 Subject: Set Devise's allow_unconfirmed_access_for to 30 days --- app/models/user.rb | 7 +++++++ config/initializers/8_devise.rb | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index ac83c8e3256..4adc44a9375 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1505,6 +1505,13 @@ class User < ApplicationRecord super end + # override from Devise::Confirmable + def confirmation_period_valid? + return false if Feature.disabled?(:soft_email_confirmation) + + super + end + private def default_private_profile_to_false diff --git a/config/initializers/8_devise.rb b/config/initializers/8_devise.rb index 3dd12c7e64d..8ef9ff6b7fc 100644 --- a/config/initializers/8_devise.rb +++ b/config/initializers/8_devise.rb @@ -81,7 +81,7 @@ Devise.setup do |config| # You can use this to let your user access some features of your application # without confirming the account, but blocking it after a certain period # (ie 2 days). - # config.allow_unconfirmed_access_for = 2.days + config.allow_unconfirmed_access_for = 30.days # Defines which key will be used when confirming an account # config.confirmation_keys = [ :email ] -- cgit v1.2.1 From a0bbfa9fc3da98f9dfa3a626a9dcd9816b88e5ed Mon Sep 17 00:00:00 2001 From: Alex Buijs Date: Wed, 31 Jul 2019 16:49:52 +0200 Subject: Don't redirect to the Almost there page Don't redirect to the Almost there page after registration and after resending confirmation instructions --- app/controllers/confirmations_controller.rb | 2 +- app/controllers/registrations_controller.rb | 4 +- spec/controllers/registrations_controller_spec.rb | 31 ++++++++++++-- spec/features/users/signup_spec.rb | 49 ++++++++++++++++++----- 4 files changed, 68 insertions(+), 18 deletions(-) diff --git a/app/controllers/confirmations_controller.rb b/app/controllers/confirmations_controller.rb index 2ae500a2fdf..b192189ba3c 100644 --- a/app/controllers/confirmations_controller.rb +++ b/app/controllers/confirmations_controller.rb @@ -11,7 +11,7 @@ class ConfirmationsController < Devise::ConfirmationsController protected def after_resending_confirmation_instructions_path_for(resource) - users_almost_there_path + Feature.enabled?(:soft_email_confirmation) ? stored_location_for(resource) || dashboard_projects_path : users_almost_there_path end def after_confirmation_path_for(resource_name, resource) diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 638934694e0..1099773c904 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -68,12 +68,12 @@ class RegistrationsController < Devise::RegistrationsController def after_sign_up_path_for(user) Gitlab::AppLogger.info(user_created_message(confirmed: user.confirmed?)) - user.confirmed? ? stored_location_for(user) || dashboard_projects_path : users_almost_there_path + user.confirmed? || Feature.enabled?(:soft_email_confirmation) ? stored_location_for(user) || dashboard_projects_path : users_almost_there_path end def after_inactive_sign_up_path_for(resource) Gitlab::AppLogger.info(user_created_message) - users_almost_there_path + Feature.enabled?(:soft_email_confirmation) ? dashboard_projects_path : users_almost_there_path end private diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb index faf3c990cb2..aa3622a1194 100644 --- a/spec/controllers/registrations_controller_spec.rb +++ b/spec/controllers/registrations_controller_spec.rb @@ -26,13 +26,36 @@ describe RegistrationsController do end context 'when send_user_confirmation_email is true' do - it 'does not authenticate user and sends confirmation email' do + before do stub_application_setting(send_user_confirmation_email: true) + end + + context 'when soft email confirmation is not enabled' do + before do + stub_feature_flags(soft_email_confirmation: false) + allow(User).to receive(:allow_unconfirmed_access_for).and_return 0 + end + + it 'does not authenticate the user and sends a confirmation email' do + post(:create, params: user_params) + + expect(ActionMailer::Base.deliveries.last.to.first).to eq(user_params[:user][:email]) + expect(subject.current_user).to be_nil + end + end + + context 'when soft email confirmation is enabled' do + before do + stub_feature_flags(soft_email_confirmation: true) + allow(User).to receive(:allow_unconfirmed_access_for).and_return 2.days + end - post(:create, params: user_params) + it 'authenticates the user and sends a confirmation email' do + post(:create, params: user_params) - expect(ActionMailer::Base.deliveries.last.to.first).to eq(user_params[:user][:email]) - expect(subject.current_user).to be_nil + expect(ActionMailer::Base.deliveries.last.to.first).to eq(user_params[:user][:email]) + expect(response).to redirect_to(dashboard_projects_path) + end end end diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb index f5897bffaf0..00793eb28e5 100644 --- a/spec/features/users/signup_spec.rb +++ b/spec/features/users/signup_spec.rb @@ -162,24 +162,51 @@ describe 'Signup' do end context 'with no errors' do - context "when sending confirmation email" do + context 'when sending confirmation email' do before do stub_application_setting(send_user_confirmation_email: true) end - it 'creates the user account and sends a confirmation email' do - visit root_path + context 'when soft email confirmation is not enabled' do + before do + stub_feature_flags(soft_email_confirmation: false) + end - fill_in 'new_user_name', with: new_user.name - fill_in 'new_user_username', with: new_user.username - fill_in 'new_user_email', with: new_user.email - fill_in 'new_user_email_confirmation', with: new_user.email - fill_in 'new_user_password', with: new_user.password + it 'creates the user account and sends a confirmation email' do + visit root_path + + fill_in 'new_user_name', with: new_user.name + fill_in 'new_user_username', with: new_user.username + fill_in 'new_user_email', with: new_user.email + fill_in 'new_user_email_confirmation', with: new_user.email + fill_in 'new_user_password', with: new_user.password + + expect { click_button 'Register' }.to change { User.count }.by(1) + + expect(current_path).to eq users_almost_there_path + expect(page).to have_content('Please check your email to confirm your account') + end + end + + context 'when soft email confirmation is enabled' do + before do + stub_feature_flags(soft_email_confirmation: true) + end + + it 'creates the user account and sends a confirmation email' do + visit root_path + + fill_in 'new_user_name', with: new_user.name + fill_in 'new_user_username', with: new_user.username + fill_in 'new_user_email', with: new_user.email + fill_in 'new_user_email_confirmation', with: new_user.email + fill_in 'new_user_password', with: new_user.password - expect { click_button 'Register' }.to change { User.count }.by(1) + expect { click_button 'Register' }.to change { User.count }.by(1) - expect(current_path).to eq users_almost_there_path - expect(page).to have_content("Please check your email to confirm your account") + expect(current_path).to eq dashboard_projects_path + expect(page).to have_content("Please check your email (#{new_user.email}) to verify that you own this address.") + end end end -- cgit v1.2.1 From f346e212e556fcfd8050f08bc27a295d0396cdd3 Mon Sep 17 00:00:00 2001 From: Alex Buijs Date: Wed, 31 Jul 2019 16:53:37 +0200 Subject: Add some feature specs --- spec/features/users/login_spec.rb | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb index dac8c8e7a29..bd70ecc5a72 100644 --- a/spec/features/users/login_spec.rb +++ b/spec/features/users/login_spec.rb @@ -745,4 +745,39 @@ describe 'Login' do end end end + + context 'when sending confirmation email and not yet confirmed' do + let!(:user) { create(:user, confirmed_at: nil) } + let(:grace_period) { 2.days } + + before do + stub_application_setting(send_user_confirmation_email: true) + stub_feature_flags(soft_email_confirmation: true) + allow(User).to receive(:allow_unconfirmed_access_for).and_return grace_period + end + + it 'allows login and shows a flash warning to confirm the email address' do + expect(authentication_metrics).to increment(:user_authenticated_counter) + + gitlab_sign_in(user) + + expect(current_path).to eq root_path + expect(page).to have_content("Please check your email (#{user.email}) to verify that you own this address.") + end + + context "when not having confirmed within Devise's allow_unconfirmed_access_for time" do + it 'does not allow login and shows a flash alert to confirm the email address' do + travel_to((grace_period + 1.day).from_now) do + expect(authentication_metrics) + .to increment(:user_unauthenticated_counter) + .and increment(:user_session_destroyed_counter).twice + + gitlab_sign_in(user) + + expect(current_path).to eq new_user_session_path + expect(page).to have_content('You have to confirm your email address before continuing.') + end + end + end + end end -- cgit v1.2.1 From 2135d0e5b26f5660f6777d47c3edda3330424641 Mon Sep 17 00:00:00 2001 From: Alex Buijs Date: Thu, 1 Aug 2019 12:36:22 +0200 Subject: Add locale translations --- locale/gitlab.pot | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index f0254be2044..9e2a8959b24 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -7937,6 +7937,9 @@ msgstr "" msgid "Please add a list to your board first" msgstr "" +msgid "Please check your email (%{email}) to verify that you own this address. Didn't receive it? %{resend_link}. Wrong email address? %{update_link}." +msgstr "" + msgid "Please choose a group URL with no special characters." msgstr "" @@ -9310,6 +9313,9 @@ msgstr "" msgid "Resend invite" msgstr "" +msgid "Resend it" +msgstr "" + msgid "Reset health check access token" msgstr "" @@ -12059,6 +12065,9 @@ msgstr "" msgid "Update failed" msgstr "" +msgid "Update it" +msgstr "" + msgid "Update now" msgstr "" -- cgit v1.2.1 From 4b2c2f1275ff6beecab8f7b5140f5ddc60cf340c Mon Sep 17 00:00:00 2001 From: Alex Buijs Date: Thu, 1 Aug 2019 17:26:54 +0200 Subject: Fix invite spec The invitation flow changed a bit, because now there is no more need to sign in after confirming. When signing up with a different email address, the user will see the invitation page straight after signing up when redirected, without needing to sign in. --- spec/features/invites_spec.rb | 72 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 14 deletions(-) diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb index 855cf22642e..2a1980346e9 100644 --- a/spec/features/invites_spec.rb +++ b/spec/features/invites_spec.rb @@ -16,11 +16,10 @@ describe 'Invites' do group_invite.generate_invite_token! end - def confirm_email_and_sign_in(new_user) + def confirm_email(new_user) new_user_token = User.find_by_email(new_user.email).confirmation_token visit user_confirmation_path(confirmation_token: new_user_token) - fill_in_sign_in_form(new_user) end def fill_in_sign_up_form(new_user) @@ -154,17 +153,41 @@ describe 'Invites' do context 'email confirmation enabled' do let(:send_email_confirmation) { true } - it 'signs up and redirects to root page with all the project/groups invitation automatically accepted' do - fill_in_sign_up_form(new_user) - confirm_email_and_sign_in(new_user) + context 'when soft email confirmation is not enabled' do + before do + # stub_feature_flags(soft_email_confirmation: false) + allow(User).to receive(:allow_unconfirmed_access_for).and_return 0 + end - expect(current_path).to eq(root_path) - expect(page).to have_content(project.full_name) - visit group_path(group) - expect(page).to have_content(group.full_name) + it 'signs up and redirects to root page with all the project/groups invitation automatically accepted' do + fill_in_sign_up_form(new_user) + confirm_email(new_user) + fill_in_sign_in_form(new_user) + + expect(current_path).to eq(root_path) + expect(page).to have_content(project.full_name) + visit group_path(group) + expect(page).to have_content(group.full_name) + end end - it "doesn't accept invitations until the user confirm his email" do + context 'when soft email confirmation is enabled' do + before do + allow(User).to receive(:allow_unconfirmed_access_for).and_return 2.days + end + + it 'signs up and redirects to root page with all the project/groups invitation automatically accepted' do + fill_in_sign_up_form(new_user) + confirm_email(new_user) + + expect(current_path).to eq(root_path) + expect(page).to have_content(project.full_name) + visit group_path(group) + expect(page).to have_content(group.full_name) + end + end + + it "doesn't accept invitations until the user confirms his email" do fill_in_sign_up_form(new_user) sign_in(owner) @@ -175,11 +198,32 @@ describe 'Invites' do context 'the user sign-up using a different email address' do let(:invite_email) { build_stubbed(:user).email } - it 'signs up and redirects to the invitation page' do - fill_in_sign_up_form(new_user) - confirm_email_and_sign_in(new_user) + context 'when soft email confirmation is not enabled' do + before do + stub_feature_flags(soft_email_confirmation: false) + allow(User).to receive(:allow_unconfirmed_access_for).and_return 0 + end - expect(current_path).to eq(invite_path(group_invite.raw_invite_token)) + it 'signs up and redirects to the invitation page' do + fill_in_sign_up_form(new_user) + confirm_email(new_user) + fill_in_sign_in_form(new_user) + + expect(current_path).to eq(invite_path(group_invite.raw_invite_token)) + end + end + + context 'when soft email confirmation is enabled' do + before do + stub_feature_flags(soft_email_confirmation: true) + allow(User).to receive(:allow_unconfirmed_access_for).and_return 2.days + end + + it 'signs up and redirects to the invitation page' do + fill_in_sign_up_form(new_user) + + expect(current_path).to eq(invite_path(group_invite.raw_invite_token)) + end end end end -- cgit v1.2.1 From 1a7280220503a4bdcbed6e0b641a22be2368a626 Mon Sep 17 00:00:00 2001 From: Alexander Oleynikov Date: Thu, 8 Aug 2019 18:14:21 +0000 Subject: Remove inoperative >/dev/null --- doc/ci/ssh_keys/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ci/ssh_keys/README.md b/doc/ci/ssh_keys/README.md index d9f022a7125..b6aebd3bd78 100644 --- a/doc/ci/ssh_keys/README.md +++ b/doc/ci/ssh_keys/README.md @@ -76,7 +76,7 @@ to access it. This is where an SSH key pair comes in handy. ## without extra base64 encoding. ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556 ## - - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null + - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - ## ## Create the SSH directory and give it the right permissions -- cgit v1.2.1 From 20ac5e6d4b1e1b6807e13b11daaedd2fb47bd3fc Mon Sep 17 00:00:00 2001 From: Armin Hohenegger Date: Sat, 10 Aug 2019 19:11:20 +0200 Subject: fix handling of empty ref_name parameter string in commits api when params[:ref_name] is set to "" by passing an empty query parameter to the api it is evaluated as false by the || operator. The use of active support core extensions presence method fixes the original implemantation. https://guides.rubyonrails.org/active_support_core_extensions.html#presence --- changelogs/unreleased/fix-commits-api-empty-refname.yml | 5 +++++ lib/api/commits.rb | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/fix-commits-api-empty-refname.yml diff --git a/changelogs/unreleased/fix-commits-api-empty-refname.yml b/changelogs/unreleased/fix-commits-api-empty-refname.yml new file mode 100644 index 00000000000..efdb950e45d --- /dev/null +++ b/changelogs/unreleased/fix-commits-api-empty-refname.yml @@ -0,0 +1,5 @@ +--- +title: Fix 500 errors in commits api caused by empty ref_name parameter +merge_request: +author: +type: fixed diff --git a/lib/api/commits.rb b/lib/api/commits.rb index e4f4e79cd46..a2f3e87ebd2 100644 --- a/lib/api/commits.rb +++ b/lib/api/commits.rb @@ -43,7 +43,7 @@ module API path = params[:path] before = params[:until] after = params[:since] - ref = params[:ref_name] || user_project.try(:default_branch) || 'master' unless params[:all] + ref = params[:ref_name].presence || user_project.try(:default_branch) || 'master' unless params[:all] offset = (params[:page] - 1) * params[:per_page] all = params[:all] with_stats = params[:with_stats] -- cgit v1.2.1 From 89bccb02d1aadb6f336576a16598ba95aad14115 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Mon, 12 Aug 2019 14:50:37 +0100 Subject: Don't use go mod vendor This change comes out of a discussion between Ben Kochie and me, around this MR: https://gitlab.com/gitlab-org/gitlab-pages/merge_requests/164 gitlab-elasticsearch-indexer already uses `go mod` without a `vendor/` directory. It has caused some intermittent build failures in the gitlab-ce/ee CI pipelines, but has otherwise been fine. I think that treating our Go dependencies in the same way we do our Ruby or Node.js ones is reasonable, and it has some minor benefits: * Contributors find it easier to submit MRs * MRs are easier to review * Makefiles are easier to write --- doc/development/go_guide/index.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md index 9f0ac8cc753..83444093f9c 100644 --- a/doc/development/go_guide/index.md +++ b/doc/development/go_guide/index.md @@ -107,6 +107,32 @@ Modules](https://github.com/golang/go/wiki/Modules). It provides a way to define and lock dependencies for reproducible builds. It should be used whenever possible. +When Go Modules are in use, there should not be a `vendor/` directory. Instead, +Go will automatically download dependencies when they are needed to build the +project. This is in line with how dependencies are handled with Bundler in Ruby +projects, and makes merge requests easier to review. + +In some cases, such as building a Go project for it to act as a dependency of a +CI run for another project, removing the `vendor/` directory means the code must +be downloaded repeatedly, which can lead to intermittent problems due to rate +limiting or network failures. In these circumstances, you should cache the +downloaded code between runs with a `.gitlab-ci.yml` snippet like this: + +```yaml +.go-cache: + variables: + GOPATH: $CI_PROJECT_DIR/.go + before_script: + - mkdir -p .go + cache: + paths: + - .go/pkg/mod/ + +test: + extends: .go-cache + # ... +``` + There was a [bug on modules checksums](https://github.com/golang/go/issues/29278) in Go < v1.11.4, so make sure to use at least this version to avoid `checksum mismatch` errors. -- cgit v1.2.1 From 54ddc018ac71f0ec7379c8528144bb9192ced510 Mon Sep 17 00:00:00 2001 From: Alex Buijs Date: Mon, 12 Aug 2019 17:40:24 +0200 Subject: Incorporate feedback fixes --- app/controllers/concerns/confirm_email_warning.rb | 2 +- app/controllers/registrations_controller.rb | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/controllers/concerns/confirm_email_warning.rb b/app/controllers/concerns/confirm_email_warning.rb index 8e2d08c9193..5a4b5897a4f 100644 --- a/app/controllers/concerns/confirm_email_warning.rb +++ b/app/controllers/concerns/confirm_email_warning.rb @@ -10,9 +10,9 @@ module ConfirmEmailWarning protected def set_confirm_warning - return if peek_request? || json_request? || !request.get? return unless current_user return if current_user.confirmed? + return if peek_request? || json_request? || !request.get? email = current_user.unconfirmed_email || current_user.email diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 1099773c904..e4ff21bc952 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -68,7 +68,7 @@ class RegistrationsController < Devise::RegistrationsController def after_sign_up_path_for(user) Gitlab::AppLogger.info(user_created_message(confirmed: user.confirmed?)) - user.confirmed? || Feature.enabled?(:soft_email_confirmation) ? stored_location_for(user) || dashboard_projects_path : users_almost_there_path + confirmed_or_unconfirmed_access_allowed(user) ? stored_location_or_dashboard(user) : users_almost_there_path end def after_inactive_sign_up_path_for(resource) @@ -134,4 +134,12 @@ class RegistrationsController < Devise::RegistrationsController def terms_accepted? Gitlab::Utils.to_boolean(params[:terms_opt_in]) end + + def confirmed_or_unconfirmed_access_allowed(user) + user.confirmed? || Feature.enabled?(:soft_email_confirmation) + end + + def stored_location_or_dashboard(user) + stored_location_for(user) || dashboard_projects_path + end end -- cgit v1.2.1 From 4882303760c9f22112985f78746f2416b701a47b Mon Sep 17 00:00:00 2001 From: Denys Mishunov Date: Mon, 12 Aug 2019 18:13:12 +0200 Subject: Fixed deletion of directories in Web IDE --- app/assets/javascripts/ide/stores/utils.js | 2 +- .../unreleased/64677-delete-directory-webide.yml | 5 ++++ spec/javascripts/ide/stores/utils_spec.js | 35 ++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/64677-delete-directory-webide.yml diff --git a/app/assets/javascripts/ide/stores/utils.js b/app/assets/javascripts/ide/stores/utils.js index 04e86afb268..52200ce7847 100644 --- a/app/assets/javascripts/ide/stores/utils.js +++ b/app/assets/javascripts/ide/stores/utils.js @@ -129,7 +129,7 @@ export const commitActionForFile = file => { export const getCommitFiles = stagedFiles => stagedFiles.reduce((acc, file) => { - if (file.moved) return acc; + if (file.moved || file.type === 'tree') return acc; return acc.concat({ ...file, diff --git a/changelogs/unreleased/64677-delete-directory-webide.yml b/changelogs/unreleased/64677-delete-directory-webide.yml new file mode 100644 index 00000000000..27d596b6b19 --- /dev/null +++ b/changelogs/unreleased/64677-delete-directory-webide.yml @@ -0,0 +1,5 @@ +--- +title: Fixed removing directories in Web IDE +merge_request: 31727 +author: +type: fixed diff --git a/spec/javascripts/ide/stores/utils_spec.js b/spec/javascripts/ide/stores/utils_spec.js index bceb3a8db91..0fc9519a6bf 100644 --- a/spec/javascripts/ide/stores/utils_spec.js +++ b/spec/javascripts/ide/stores/utils_spec.js @@ -261,6 +261,41 @@ describe('Multi-file store utils', () => { }, ]); }); + + it('filters out folders from the list', () => { + const files = [ + { + path: 'a', + type: 'blob', + deleted: true, + }, + { + path: 'c', + type: 'tree', + deleted: true, + }, + { + path: 'c/d', + type: 'blob', + deleted: true, + }, + ]; + + const flattendFiles = utils.getCommitFiles(files); + + expect(flattendFiles).toEqual([ + { + path: 'a', + type: 'blob', + deleted: true, + }, + { + path: 'c/d', + type: 'blob', + deleted: true, + }, + ]); + }); }); describe('mergeTrees', () => { -- cgit v1.2.1 From 7d02c3f8a161ee2d9515328bb6e4ebce614dd976 Mon Sep 17 00:00:00 2001 From: Philipp Hasper Date: Tue, 13 Aug 2019 09:58:28 +0000 Subject: Removed duplicate Live preview entry for MR docs --- doc/user/project/merge_requests/index.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md index 7ff30d1b813..57a2a720e17 100644 --- a/doc/user/project/merge_requests/index.md +++ b/doc/user/project/merge_requests/index.md @@ -480,15 +480,6 @@ without having to check the entire job log. [Read more about JUnit test reports](../../../ci/junit_test_reports.md). -## Live preview with Review Apps - -If you configured [Review Apps](https://about.gitlab.com/features/review-apps/) for your project, -you can preview the changes submitted to a feature-branch through a merge request -in a per-branch basis. No need to checkout the branch, install and preview locally; -all your changes will be available to preview by anyone with the Review Apps link. - -[Read more about Review Apps.](../../../ci/review_apps/index.md) - ## Merge request diff file navigation When reviewing changes in the **Changes** tab the diff can be navigated using -- cgit v1.2.1 From e70cfdebc70e4bf12f6d8393e1d36e92b3de2219 Mon Sep 17 00:00:00 2001 From: Armin Hohenegger Date: Tue, 13 Aug 2019 23:00:14 +0200 Subject: add a test for empty ref_name to api commits spec --- spec/requests/api/commits_spec.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb index e8e17228523..1b139bfa6f2 100644 --- a/spec/requests/api/commits_spec.rb +++ b/spec/requests/api/commits_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 require 'spec_helper' require 'mime/types' @@ -126,6 +127,12 @@ describe API::Commits do end end + context "with empty ref_name parameter" do + let(:route) { "/projects/#{project_id}/repository/commits?ref_name=" } + + it_behaves_like 'project commits' + end + context "path optional parameter" do it "returns project commits matching provided path parameter" do path = 'files/ruby/popen.rb' -- cgit v1.2.1 From eb35728201b7f7c36979c314b86fdaafc564e190 Mon Sep 17 00:00:00 2001 From: Armin Hohenegger Date: Tue, 13 Aug 2019 23:36:22 +0200 Subject: remove encoding comment created by emacs ruby-mode --- spec/requests/api/commits_spec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb index 1b139bfa6f2..5e6ff40e8cf 100644 --- a/spec/requests/api/commits_spec.rb +++ b/spec/requests/api/commits_spec.rb @@ -1,4 +1,3 @@ -# coding: utf-8 require 'spec_helper' require 'mime/types' -- cgit v1.2.1 From 72541807b34348e7fa7e7d1ef7d119376382d8af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Trzci=C5=84ski?= Date: Wed, 14 Aug 2019 15:59:44 +0200 Subject: Enable DAG support by default This toggles the ci_dag_support flag to be on by default. This relies on ci_dag_limit_needs to be present to reduce amount of inter-dependencies between jobs --- app/models/ci/build.rb | 2 +- app/services/ci/process_pipeline_service.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index f705e67121f..3c0efca31db 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -716,7 +716,7 @@ module Ci depended_jobs = depends_on_builds # find all jobs that are needed - if Feature.enabled?(:ci_dag_support, project) && needs.exists? + if Feature.enabled?(:ci_dag_support, project, default_enabled: true) && needs.exists? depended_jobs = depended_jobs.where(name: needs.select(:name)) end diff --git a/app/services/ci/process_pipeline_service.rb b/app/services/ci/process_pipeline_service.rb index 99d4ff9ecd1..062a47f6027 100644 --- a/app/services/ci/process_pipeline_service.rb +++ b/app/services/ci/process_pipeline_service.rb @@ -40,7 +40,7 @@ module Ci def process_builds_with_needs(trigger_build_ids) return false unless trigger_build_ids.present? - return false unless Feature.enabled?(:ci_dag_support, project) + return false unless Feature.enabled?(:ci_dag_support, project, default_enabled: true) # rubocop: disable CodeReuse/ActiveRecord trigger_build_names = pipeline.statuses @@ -97,7 +97,7 @@ module Ci # rubocop: enable CodeReuse/ActiveRecord def created_processables_without_needs - if Feature.enabled?(:ci_dag_support, project) + if Feature.enabled?(:ci_dag_support, project, default_enabled: true) pipeline.processables.created.without_needs else pipeline.processables.created -- cgit v1.2.1 From 8c2c4e4d75ec60182e37ddaf637bc25095bdd57f Mon Sep 17 00:00:00 2001 From: Takuya Noguchi Date: Wed, 14 Aug 2019 17:48:00 +0100 Subject: Upgrade babel to 7.5.5 Signed-off-by: Takuya Noguchi --- changelogs/unreleased/update-babel-to-7-5-5.yml | 5 ++++ package.json | 8 +++--- yarn.lock | 36 ++++++++++++------------- 3 files changed, 27 insertions(+), 22 deletions(-) create mode 100644 changelogs/unreleased/update-babel-to-7-5-5.yml diff --git a/changelogs/unreleased/update-babel-to-7-5-5.yml b/changelogs/unreleased/update-babel-to-7-5-5.yml new file mode 100644 index 00000000000..c498e2adfe8 --- /dev/null +++ b/changelogs/unreleased/update-babel-to-7-5-5.yml @@ -0,0 +1,5 @@ +--- +title: Upgrade babel to 7.5.5 +merge_request: 31819 +author: Takuya Noguchi +type: other diff --git a/package.json b/package.json index 803aebcb5fd..9c9a7687fc2 100644 --- a/package.json +++ b/package.json @@ -30,13 +30,13 @@ "webpack-vrt": "NODE_OPTIONS=\"--max-old-space-size=3584\" NODE_ENV=production webpack --config config/webpack.config.review_toolbar.js" }, "dependencies": { - "@babel/core": "^7.4.4", - "@babel/plugin-proposal-class-properties": "^7.4.4", + "@babel/core": "^7.5.5", + "@babel/plugin-proposal-class-properties": "^7.5.5", "@babel/plugin-proposal-json-strings": "^7.2.0", "@babel/plugin-proposal-private-methods": "^7.4.4", "@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/plugin-syntax-import-meta": "^7.2.0", - "@babel/preset-env": "^7.4.4", + "@babel/preset-env": "^7.5.5", "@gitlab/csslab": "^1.9.0", "@gitlab/svgs": "^1.67.0", "@gitlab/ui": "5.15.0", @@ -145,7 +145,7 @@ "xterm": "^3.5.0" }, "devDependencies": { - "@babel/plugin-transform-modules-commonjs": "^7.2.0", + "@babel/plugin-transform-modules-commonjs": "^7.5.0", "@gitlab/eslint-config": "^1.6.0", "@gitlab/eslint-plugin-i18n": "^1.1.0", "@gitlab/eslint-plugin-vue-i18n": "^1.2.0", diff --git a/yarn.lock b/yarn.lock index ed1f06523c0..5a59f149e8a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,7 +9,7 @@ dependencies: "@babel/highlight" "^7.0.0" -"@babel/core@>=7.2.2", "@babel/core@^7.1.0", "@babel/core@^7.1.2", "@babel/core@^7.4.4": +"@babel/core@>=7.2.2", "@babel/core@^7.1.0", "@babel/core@^7.1.2", "@babel/core@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.5.5.tgz#17b2686ef0d6bc58f963dddd68ab669755582c30" integrity sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg== @@ -139,16 +139,16 @@ "@babel/types" "^7.0.0" "@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz#96115ea42a2f139e619e98ed46df6019b94414b8" - integrity sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w== + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz#f84ff8a09038dcbca1fd4355661a500937165b4a" + integrity sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-simple-access" "^7.1.0" "@babel/helper-split-export-declaration" "^7.4.4" "@babel/template" "^7.4.4" - "@babel/types" "^7.4.4" - lodash "^4.17.11" + "@babel/types" "^7.5.5" + lodash "^4.17.13" "@babel/helper-optimise-call-expression@^7.0.0": version "7.0.0" @@ -163,11 +163,11 @@ integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== "@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.4.4.tgz#a47e02bc91fb259d2e6727c2a30013e3ac13c4a2" - integrity sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q== + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" + integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw== dependencies: - lodash "^4.17.11" + lodash "^4.17.13" "@babel/helper-remap-async-to-generator@^7.1.0": version "7.1.0" @@ -225,9 +225,9 @@ "@babel/types" "^7.5.5" "@babel/highlight@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" - integrity sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw== + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" + integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== dependencies: chalk "^2.0.0" esutils "^2.0.2" @@ -252,7 +252,7 @@ "@babel/helper-remap-async-to-generator" "^7.1.0" "@babel/plugin-syntax-async-generators" "^7.2.0" -"@babel/plugin-proposal-class-properties@^7.1.0", "@babel/plugin-proposal-class-properties@^7.4.4": +"@babel/plugin-proposal-class-properties@^7.1.0", "@babel/plugin-proposal-class-properties@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.5.5.tgz#a974cfae1e37c3110e71f3c6a2e48b8e71958cd4" integrity sha512-AF79FsnWFxjlaosgdi421vmYG6/jg79bVD0dpD44QdgobzHKuLZ6S3vl8la9qIeSwGi8i1fS0O1mfuDAAdo1/A== @@ -833,7 +833,7 @@ "@babel/helper-regex" "^7.4.4" regexpu-core "^4.5.4" -"@babel/preset-env@^7.1.0", "@babel/preset-env@^7.4.4": +"@babel/preset-env@^7.1.0", "@babel/preset-env@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.5.5.tgz#bc470b53acaa48df4b8db24a570d6da1fef53c9a" integrity sha512-GMZQka/+INwsMz1A5UEql8tG015h5j/qjptpKY2gJ7giy8ohzU710YciJB5rcKsWGWHiW3RUnHib0E5/m3Tp3A== @@ -914,9 +914,9 @@ integrity sha512-FBMd0IiARPtH5aaOFUVki6evHiJQiY0pFy7fizyRF7dtwc+el3nwpzvhb9qBNzceG1OIJModG1xpE0DDFjPXwA== "@babel/standalone@^7.0.0": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.3.4.tgz#b622c1e522acef91b2a14f22bdcdd4f935a1a474" - integrity sha512-4L9c5i4WlGqbrjOVX0Yp8TIR5cEiw1/tPYYZENW/iuO2uI6viY38U7zALidzNfGdZIwNc+A/AWqMEWKeScWkBg== + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.5.5.tgz#9d3143f6078ff408db694a4254bd6f03c5c33962" + integrity sha512-YIp5taErC4uvp4d5urJtWMui3cpvZt83x57l4oVJNvFtDzumf3pMgRmoTSpGuEzh1yzo7jHhg3mbQmMhmKPbjA== "@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4": version "7.4.4" -- cgit v1.2.1 From 50956e5c85e29d0d1a7634068b782ffce73be479 Mon Sep 17 00:00:00 2001 From: Luke Duncalfe Date: Mon, 12 Aug 2019 10:17:32 +1200 Subject: Link more issues in Design Management Limitations --- doc/user/project/issues/design_management.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md index bffbcb544e3..1324a90e00b 100644 --- a/doc/user/project/issues/design_management.md +++ b/doc/user/project/issues/design_management.md @@ -35,9 +35,19 @@ to be enabled: ## Limitations -- Files uploaded must have a file extension of either `png`, `jpg`, `jpeg`, `gif`, `bmp`, `tiff` or `ico`. The [`svg` extension is not yet supported](https://gitlab.com/gitlab-org/gitlab-ee/issues/12771). +- Files uploaded must have a file extension of either `png`, `jpg`, `jpeg`, `gif`, `bmp`, `tiff` or `ico`. + The [`svg` extension is not yet supported](https://gitlab.com/gitlab-org/gitlab-ee/issues/12771). +- Design uploads are limited to 10 files at a time. - [Designs cannot yet be deleted](https://gitlab.com/gitlab-org/gitlab-ee/issues/11089). -- Design Management is [not yet supported in the project export](https://gitlab.com/gitlab-org/gitlab-ee/issues/11090). +- Design Management is + [not yet supported in the project export](https://gitlab.com/gitlab-org/gitlab-ee/issues/11090). +- Design Management data + [isn't deleted when a project is destroyed](https://gitlab.com/gitlab-org/gitlab-ee/issues/13429) yet. +- Design Management data [won't be moved](https://gitlab.com/gitlab-org/gitlab-ee/issues/13426) + when an issue is moved, nor [deleted](https://gitlab.com/gitlab-org/gitlab-ee/issues/13427) + when an issue is deleted. +- Design Management + [isn't supported by Geo](https://gitlab.com/groups/gitlab-org/-/epics/1633) yet. ## The Design Management page -- cgit v1.2.1 From 18159235a3150dbd3c404e1d7724d5e653bb21a5 Mon Sep 17 00:00:00 2001 From: Krasimir Angelov Date: Wed, 14 Aug 2019 14:17:13 +0300 Subject: Add finished_at to the internal API Deployment entity Related to https://gitlab.com/gitlab-org/gitlab-ce/issues/56130. --- app/serializers/deployment_entity.rb | 1 + app/serializers/deployment_serializer.rb | 2 +- changelogs/unreleased/56130-deployment-date.yml | 5 +++++ spec/fixtures/api/schemas/deployment.json | 2 ++ spec/serializers/deployment_entity_spec.rb | 4 ++++ 5 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/56130-deployment-date.yml diff --git a/app/serializers/deployment_entity.rb b/app/serializers/deployment_entity.rb index 943c707218d..6e91317eb20 100644 --- a/app/serializers/deployment_entity.rb +++ b/app/serializers/deployment_entity.rb @@ -18,6 +18,7 @@ class DeploymentEntity < Grape::Entity end expose :created_at + expose :finished_at expose :tag expose :last? expose :user, using: UserEntity diff --git a/app/serializers/deployment_serializer.rb b/app/serializers/deployment_serializer.rb index 04db6b88489..3fd3e1b9cc8 100644 --- a/app/serializers/deployment_serializer.rb +++ b/app/serializers/deployment_serializer.rb @@ -4,7 +4,7 @@ class DeploymentSerializer < BaseSerializer entity DeploymentEntity def represent_concise(resource, opts = {}) - opts[:only] = [:iid, :id, :sha, :created_at, :tag, :last?, :id, ref: [:name]] + opts[:only] = [:iid, :id, :sha, :created_at, :finished_at, :tag, :last?, :id, ref: [:name]] represent(resource, opts) end end diff --git a/changelogs/unreleased/56130-deployment-date.yml b/changelogs/unreleased/56130-deployment-date.yml new file mode 100644 index 00000000000..7d1e84bbaa4 --- /dev/null +++ b/changelogs/unreleased/56130-deployment-date.yml @@ -0,0 +1,5 @@ +--- +title: Add finished_at to the internal API Deployment entity +merge_request: 31808 +author: +type: other diff --git a/spec/fixtures/api/schemas/deployment.json b/spec/fixtures/api/schemas/deployment.json index 0828f113495..9216ad0060b 100644 --- a/spec/fixtures/api/schemas/deployment.json +++ b/spec/fixtures/api/schemas/deployment.json @@ -3,6 +3,7 @@ "required": [ "sha", "created_at", + "finished_at", "iid", "tag", "last?", @@ -11,6 +12,7 @@ ], "properties": { "created_at": { "type": "string" }, + "finished_at": { "type": ["string", "null"] }, "id": { "type": "integer" }, "iid": { "type": "integer" }, "last?": { "type": "boolean" }, diff --git a/spec/serializers/deployment_entity_spec.rb b/spec/serializers/deployment_entity_spec.rb index 76ad2aee5c5..c0ea2b3c389 100644 --- a/spec/serializers/deployment_entity_spec.rb +++ b/spec/serializers/deployment_entity_spec.rb @@ -32,6 +32,10 @@ describe DeploymentEntity do expect(subject).to include(:created_at) end + it 'exposes finished_at' do + expect(subject).to include(:finished_at) + end + context 'when the pipeline has another manual action' do let(:other_build) { create(:ci_build, :manual, name: 'another deploy', pipeline: pipeline) } let!(:other_deployment) { create(:deployment, deployable: other_build) } -- cgit v1.2.1 From e55c7a9a3572ad37a8b69cd2d3db9ab24b5ba5ab Mon Sep 17 00:00:00 2001 From: Paul Slaughter Date: Thu, 15 Aug 2019 10:11:36 -0500 Subject: Add key unbinds to DiscussionKeyboardNavigator Also adds comment to explain why this works on the diff-tab when it's only used in `notes-app`. https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/30144#note_204066538 --- app/assets/javascripts/mr_notes/init_notes.js | 4 ++++ .../components/discussion_keyboard_navigator.vue | 4 ++++ .../discussion_keyboard_navigator_spec.js | 27 ++++++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/app/assets/javascripts/mr_notes/init_notes.js b/app/assets/javascripts/mr_notes/init_notes.js index 8caac68e0d4..622db360d1f 100644 --- a/app/assets/javascripts/mr_notes/init_notes.js +++ b/app/assets/javascripts/mr_notes/init_notes.js @@ -59,6 +59,10 @@ export default () => { render(createElement) { const isDiffView = this.activeTab === 'diffs'; + // NOTE: Even though `discussionKeyboardNavigator` is added to the `notes-app`, + // it adds a global key listener so it works on the diffs tab as well. + // If we create a single Vue app for all of the MR tabs, we should move this + // up the tree, to the root. return createElement(discussionKeyboardNavigator, { props: { isDiffView } }, [ createElement('notes-app', { props: { diff --git a/app/assets/javascripts/notes/components/discussion_keyboard_navigator.vue b/app/assets/javascripts/notes/components/discussion_keyboard_navigator.vue index 5fc2b6ba04c..7fbfe8eebb2 100644 --- a/app/assets/javascripts/notes/components/discussion_keyboard_navigator.vue +++ b/app/assets/javascripts/notes/components/discussion_keyboard_navigator.vue @@ -25,6 +25,10 @@ export default { Mousetrap.bind('n', () => this.jumpToNextDiscussion()); Mousetrap.bind('p', () => this.jumpToPreviousDiscussion()); }, + beforeDestroy() { + Mousetrap.unbind('n'); + Mousetrap.unbind('p'); + }, methods: { ...mapActions(['expandDiscussion']), jumpToNextDiscussion() { diff --git a/spec/frontend/notes/components/discussion_keyboard_navigator_spec.js b/spec/frontend/notes/components/discussion_keyboard_navigator_spec.js index 6d50713999d..8881bedf3cc 100644 --- a/spec/frontend/notes/components/discussion_keyboard_navigator_spec.js +++ b/spec/frontend/notes/components/discussion_keyboard_navigator_spec.js @@ -74,4 +74,31 @@ describe('notes/components/discussion_keyboard_navigator', () => { expect(wrapper.vm.currentDiscussionId).toEqual(expectedPrevId); }); }); + + describe('on destroy', () => { + beforeEach(() => { + jest.spyOn(Mousetrap, 'unbind'); + + createComponent(); + + wrapper.destroy(); + }); + + it('unbinds keys', () => { + expect(Mousetrap.unbind).toHaveBeenCalledWith('n'); + expect(Mousetrap.unbind).toHaveBeenCalledWith('p'); + }); + + it('does not call jumpToNextDiscussion when pressing `n`', () => { + Mousetrap.trigger('n'); + + expect(wrapper.vm.jumpToDiscussion).not.toHaveBeenCalled(); + }); + + it('does not call jumpToNextDiscussion when pressing `p`', () => { + Mousetrap.trigger('p'); + + expect(wrapper.vm.jumpToDiscussion).not.toHaveBeenCalled(); + }); + }); }); -- cgit v1.2.1 From 3d045ea84f0c04355b9fafc3536b825768841ac3 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 15 Aug 2019 12:25:47 -0500 Subject: Fix quarantined spec by waiting for requests --- ...r_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb b/spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb index c19e46da913..6bd569e5ee2 100644 --- a/spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb +++ b/spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb @@ -3,18 +3,15 @@ require 'spec_helper' # This is a regression test for https://gitlab.com/gitlab-org/gitlab-ce/issues/37569 -# Quarantine: https://gitlab.com/gitlab-org/gitlab-ce/issues/65329 -describe 'Projects > Files > User browses a tree with a folder containing only a folder', :quarantine do +describe 'Projects > Files > User browses a tree with a folder containing only a folder', :js do let(:project) { create(:project, :empty_repo) } let(:user) { project.owner } before do - # We need to disable the tree.flat_path provided by Gitaly to reproduce the issue - allow(Gitlab::GitalyClient).to receive(:feature_enabled?).and_return(false) - project.repository.create_dir(user, 'foo/bar', branch_name: 'master', message: 'Add the foo/bar folder') sign_in(user) visit(project_tree_path(project, project.repository.root_ref)) + wait_for_requests end it 'shows the nested folder on a single row' do -- cgit v1.2.1 From 38ba59bedd8b7e2f1a4de08725d6e000bf4fde42 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 14 Aug 2019 17:29:41 -0300 Subject: Fix starrers counters after searching --- app/controllers/projects/starrers_controller.rb | 18 +-- .../projects/starrers_controller_spec.rb | 152 +++++++++++++++------ 2 files changed, 114 insertions(+), 56 deletions(-) diff --git a/app/controllers/projects/starrers_controller.rb b/app/controllers/projects/starrers_controller.rb index c8facea1d70..e4093bed0ef 100644 --- a/app/controllers/projects/starrers_controller.rb +++ b/app/controllers/projects/starrers_controller.rb @@ -5,23 +5,9 @@ class Projects::StarrersController < Projects::ApplicationController def index @starrers = UsersStarProjectsFinder.new(@project, params, current_user: @current_user).execute - - # Normally the number of public starrers is equal to the number of visible - # starrers. We need to fix the counts in two cases: when the current user - # is an admin (and can see everything) and when the current user has a - # private profile and has starred the project (and can see itself). - @public_count = - if @current_user&.admin? - @starrers.with_public_profile.count - elsif @current_user&.private_profile && has_starred_project?(@starrers) - @starrers.size - 1 - else - @starrers.size - end - - @total_count = @project.starrers.size + @public_count = @project.starrers.with_public_profile.size + @total_count = @project.starrers.size @private_count = @total_count - @public_count - @sort = params[:sort].presence || sort_value_name @starrers = @starrers.sort_by_attribute(@sort).page(params[:page]) end diff --git a/spec/controllers/projects/starrers_controller_spec.rb b/spec/controllers/projects/starrers_controller_spec.rb index 59d258e99ce..7085cba08d5 100644 --- a/spec/controllers/projects/starrers_controller_spec.rb +++ b/spec/controllers/projects/starrers_controller_spec.rb @@ -3,23 +3,33 @@ require 'spec_helper' describe Projects::StarrersController do - let(:user) { create(:user) } - let(:private_user) { create(:user, private_profile: true) } + let(:user_1) { create(:user, name: 'John') } + let(:user_2) { create(:user, name: 'Michael') } + let(:private_user) { create(:user, name: 'Michael Douglas', private_profile: true) } let(:admin) { create(:user, admin: true) } - let(:project) { create(:project, :public, :repository) } + let(:project) { create(:project, :public) } before do - user.toggle_star(project) + user_1.toggle_star(project) + user_2.toggle_star(project) private_user.toggle_star(project) end describe 'GET index' do - def get_starrers - get :index, - params: { - namespace_id: project.namespace, - project_id: project - } + def get_starrers(search: nil) + get :index, params: { namespace_id: project.namespace, project_id: project, search: search } + end + + def user_ids + assigns[:starrers].map { |s| s['user_id'] } + end + + shared_examples 'starrers counts' do + it 'starrers counts are correct' do + expect(assigns[:total_count]).to eq(3) + expect(assigns[:public_count]).to eq(2) + expect(assigns[:private_count]).to eq(1) + end end context 'when project is public' do @@ -28,55 +38,118 @@ describe Projects::StarrersController do end context 'when no user is logged in' do + context 'with no searching' do + before do + get_starrers + end + + it 'only users with public profiles are visible' do + expect(user_ids).to contain_exactly(user_1.id, user_2.id) + end + + include_examples 'starrers counts' + end + + context 'when searching by user' do + before do + get_starrers(search: 'Michael') + end + + it 'only users with public profiles are visible' do + expect(user_ids).to contain_exactly(user_2.id) + end + + include_examples 'starrers counts' + end + end + + context 'when public user is logged in' do before do - get_starrers + sign_in(user_1) end - it 'only public starrers are visible' do - user_ids = assigns[:starrers].map { |s| s['user_id'] } - expect(user_ids).to include(user.id) - expect(user_ids).not_to include(private_user.id) + context 'with no searching' do + before do + get_starrers + end + + it 'their star is also visible' do + expect(user_ids).to contain_exactly(user_1.id, user_2.id) + end + + include_examples 'starrers counts' end - it 'public/private starrers counts are correct' do - expect(assigns[:public_count]).to eq(1) - expect(assigns[:private_count]).to eq(1) + context 'when searching by user' do + before do + get_starrers(search: 'Michael') + end + + it 'only users with public profiles are visible' do + expect(user_ids).to contain_exactly(user_2.id) + end + + include_examples 'starrers counts' end end context 'when private user is logged in' do before do sign_in(private_user) - - get_starrers end - it 'their star is also visible' do - user_ids = assigns[:starrers].map { |s| s['user_id'] } - expect(user_ids).to include(user.id, private_user.id) + context 'with no searching' do + before do + get_starrers + end + + it 'their star is also visible' do + expect(user_ids).to contain_exactly(user_1.id, user_2.id, private_user.id) + end + + include_examples 'starrers counts' end - it 'public/private starrers counts are correct' do - expect(assigns[:public_count]).to eq(1) - expect(assigns[:private_count]).to eq(1) + context 'when searching by user' do + before do + get_starrers(search: 'Michael') + end + + it 'only users with public profiles are visible' do + expect(user_ids).to contain_exactly(user_2.id, private_user.id) + end + + include_examples 'starrers counts' end end context 'when admin is logged in' do before do sign_in(admin) - - get_starrers end - it 'all stars are visible' do - user_ids = assigns[:starrers].map { |s| s['user_id'] } - expect(user_ids).to include(user.id, private_user.id) + context 'with no searching' do + before do + get_starrers + end + + it 'all users are visible' do + expect(user_ids).to include(user_1.id, user_2.id, private_user.id) + end + + include_examples 'starrers counts' end - it 'public/private starrers counts are correct' do - expect(assigns[:public_count]).to eq(1) - expect(assigns[:private_count]).to eq(1) + context 'when searching by user' do + before do + get_starrers(search: 'Michael') + end + + it 'public and private starrers are visible' do + expect(user_ids).to contain_exactly(user_2.id, private_user.id) + end + + include_examples 'starrers counts' end end end @@ -95,15 +168,14 @@ describe Projects::StarrersController do context 'when user is logged in' do before do sign_in(project.creator) - end - - it 'only public starrers are visible' do get_starrers + end - user_ids = assigns[:starrers].map { |s| s['user_id'] } - expect(user_ids).to include(user.id) - expect(user_ids).not_to include(private_user.id) + it 'only users with public profiles are visible' do + expect(user_ids).to contain_exactly(user_1.id, user_2.id) end + + include_examples 'starrers counts' end end end -- cgit v1.2.1 From 4596d5d1a2eb8f918f9f59d85aed53aa232f1fcf Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 14 Aug 2019 17:48:13 -0300 Subject: Add CHANGELOG entry --- .../unreleased/66023-starrers-count-do-not-match-after-searching.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelogs/unreleased/66023-starrers-count-do-not-match-after-searching.yml diff --git a/changelogs/unreleased/66023-starrers-count-do-not-match-after-searching.yml b/changelogs/unreleased/66023-starrers-count-do-not-match-after-searching.yml new file mode 100644 index 00000000000..1caa5fa84ce --- /dev/null +++ b/changelogs/unreleased/66023-starrers-count-do-not-match-after-searching.yml @@ -0,0 +1,5 @@ +--- +title: Fix starrers counts after searching +merge_request: 31823 +author: +type: fixed -- cgit v1.2.1 From 6bcad2d178f0f2dab4a650a8c2e11ff2bbb27343 Mon Sep 17 00:00:00 2001 From: Mark Chao Date: Thu, 15 Aug 2019 16:17:00 +0800 Subject: Doc: sync ES updates --- doc/integration/elasticsearch.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md index 1c80fc543af..eee05eaef02 100644 --- a/doc/integration/elasticsearch.md +++ b/doc/integration/elasticsearch.md @@ -333,6 +333,10 @@ curl --request PUT localhost:9200/gitlab-production/_settings --data '{ Enable Elasticsearch search in **Admin > Settings > Integrations**. That's it. Enjoy it! +### Index limit + +Currently for repository and snippet files, GitLab would only index up to 1 MB of content, in order to avoid indexing timeout. + ## GitLab Elasticsearch Rake Tasks There are several rake tasks available to you via the command line: -- cgit v1.2.1 From 7dd27adc266fb20ab86cde5747694ca9b1b2971b Mon Sep 17 00:00:00 2001 From: Marcel Amirault Date: Fri, 16 Aug 2019 03:36:06 +0000 Subject: Remove indentation from list --- doc/ci/directed_acyclic_graph/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ci/directed_acyclic_graph/index.md b/doc/ci/directed_acyclic_graph/index.md index 2f000719c04..e54be9f3bd9 100644 --- a/doc/ci/directed_acyclic_graph/index.md +++ b/doc/ci/directed_acyclic_graph/index.md @@ -72,5 +72,5 @@ giving your powerful options for parallelization within your pipeline. A directed acyclic graph is a complicated feature, and as of the initial MVC there are certain use cases that you may need to work around. For more information: - - [`needs` requirements and limitations](../yaml/README.md#requirements-and-limitations). - - Related epic [gitlab-org#1716](https://gitlab.com/groups/gitlab-org/-/epics/1716). +- [`needs` requirements and limitations](../yaml/README.md#requirements-and-limitations). +- Related epic [gitlab-org#1716](https://gitlab.com/groups/gitlab-org/-/epics/1716). -- cgit v1.2.1 From 52ec0b7b5c69d09695c1b0db2ad18810742a5428 Mon Sep 17 00:00:00 2001 From: Martin Wortschack Date: Fri, 16 Aug 2019 03:44:15 +0000 Subject: Revert adding productivity analytics docs --- doc/user/analytics/productivity_analytics.md | 69 ---------------------------- 1 file changed, 69 deletions(-) delete mode 100644 doc/user/analytics/productivity_analytics.md diff --git a/doc/user/analytics/productivity_analytics.md b/doc/user/analytics/productivity_analytics.md deleted file mode 100644 index db3e37bd0fb..00000000000 --- a/doc/user/analytics/productivity_analytics.md +++ /dev/null @@ -1,69 +0,0 @@ -# Productivity Analytics **(PREMIUM)** - -> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/12079) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.2 (enabled by feature flags `analytics` and `productivity_analytics`). - -Track development velocity with Productivity Analytics. - -For many companies, the development cycle is a blackbox and getting an estimate of how -long, on average, it takes to deliver features is an enormous endeavor. - -While [Cycle Analytics](../project/cycle_analytics.md) focuses on the entire -SDLC process, Productivity Analytics provides a way for Engineering Management to -drill down in a systematic way to uncover patterns and causes for success or failure at -an individual, project or group level. - -Productivity can slow down for many reasons ranging from degrading code base to quickly -growing teams. In order to investigate, department or team leaders can start by visualizing the time -it takes for merge requests to be merged. - -## Supported features - -Productivity Analytics allows GitLab users to: - -- Visualize typical Merge Request lifetime and statistics. Use a histogram - that shows the distribution of the time elapsed between creating and merging - Merge Requests. -- Drill down into the most time consuming Merge Requests, select a number of outliers, - and filter down all subsequent charts to investigate potential causes. -- Filter by group, project, author, label, milestone, or a specific date range. - Filter down, for example, to the Merge Requests of a specific author in a group - or project during a milestone or specific date range. - -## Accessing metrics and visualizations - -To access the **Productivity Analytics** page, go to **Analytics > Productivity Analytics**. - -The following metrics and visualizations are available on a project or group level: - -- Histogram showing the number of Merge Request that took a specified number of days to - merge after creation. Select a specific column to filter down subsequent charts. -- Histogram showing a breakdown of the time taken (in hours) to merge a Merge Request. - The following intervals are available: - - Time from first commit to first comment. - - Time from first comment until last commit. - - Time from last commit to merge. -- Histogram showing the size or complexity of a Merge Request, using the following: - - Number of commits per Merge Request. - - Number of lines of code per commit. - - Number of files touched. -- Table showing list of Merge Requests with their respective times and size metrics. - Can be sorted by the above metrics. - - Users can sort by any of the above metrics - -## Retrieving data - -Users can retrieve three months of data when they deploy Productivity Analytics for the first time. - -To retrieve data for a different time span, run the following in the GitLab directory: - -```sh -MERGED_AT_AFTER = rake gitlab:productivity_analytics:recalc -``` - -## Permissions - -The **Productivity Analytics** dashboard can be accessed only: - -- On GitLab instances and namespaces on - [Premium or Silver tier](https://about.gitlab.com/pricing/) and above. -- By users with [Reporter access](../permissions.md) and above. -- cgit v1.2.1 From f965a5f91d5378d0b8b0c84661cf5f8ab4c1e789 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Fri, 16 Aug 2019 03:47:40 +0000 Subject: Document option to set Security Dashboard as default view for groups --- doc/user/profile/preferences.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/user/profile/preferences.md b/doc/user/profile/preferences.md index 5bd4b263a58..82a6d2b3703 100644 --- a/doc/user/profile/preferences.md +++ b/doc/user/profile/preferences.md @@ -87,6 +87,16 @@ You have 8 options here that you can use for your default dashboard view: - Assigned Merge Requests - Operations Dashboard **(PREMIUM)** +### Group overview content + +The **Group overview content** dropdown allows you to choose what information is +displayed on a group’s home page. + +You can choose between 2 options: + +- Details (default) +- [Security dashboard](../application_security/security_dashboard/index.md) **(ULTIMATE)** + ### Project overview content The project overview content setting allows you to choose what content you want to -- cgit v1.2.1 From 1853aade2df03f2531c65b5cb2959b811a6bf8b4 Mon Sep 17 00:00:00 2001 From: Alexander Tanayno Date: Fri, 16 Aug 2019 04:41:09 +0000 Subject: Add a note about the lack of arm64 support --- doc/user/project/clusters/index.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md index ffaa07cb3a4..cf3a3fef79f 100644 --- a/doc/user/project/clusters/index.md +++ b/doc/user/project/clusters/index.md @@ -173,6 +173,9 @@ Starting from [GitLab 12.1](https://gitlab.com/gitlab-org/gitlab-ce/issues/55902 ### Add existing Kubernetes cluster +NOTE: **Note:** +Kubernetes integration is not supported for arm64 clusters. See the issue [Helm Tiller fails to install on arm64 cluster](https://gitlab.com/gitlab-org/gitlab-ce/issues/64044) for details. + To add an existing Kubernetes cluster to your project: 1. Navigate to your project's **Operations > Kubernetes** page. -- cgit v1.2.1 From 19db315734d54d6850b0139dda75da758b55af56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jarka=20Ko=C5=A1anov=C3=A1?= Date: Tue, 13 Aug 2019 10:30:32 +0200 Subject: Add rake tasks for migrating leacy uploads - move uploads created by AttachmentUploader - handle also files created for legacy_diff_notes --- changelogs/unreleased/50070-legacy-attachments.yml | 5 + doc/administration/logs.md | 6 + doc/administration/raketasks/uploads/migrate.md | 10 + doc/development/rake_tasks.md | 1 + .../background_migration/legacy_upload_mover.rb | 140 ++++++++++ .../legacy_uploads_migrator.rb | 23 ++ lib/gitlab/background_migration/logger.rb | 12 + lib/tasks/gitlab/uploads/legacy.rake | 27 ++ spec/factories/uploads.rb | 5 +- .../legacy_upload_mover_spec.rb | 296 +++++++++++++++++++++ .../legacy_uploads_migrator_spec.rb | 63 +++++ 11 files changed, 584 insertions(+), 4 deletions(-) create mode 100644 changelogs/unreleased/50070-legacy-attachments.yml create mode 100644 lib/gitlab/background_migration/legacy_upload_mover.rb create mode 100644 lib/gitlab/background_migration/legacy_uploads_migrator.rb create mode 100644 lib/gitlab/background_migration/logger.rb create mode 100644 lib/tasks/gitlab/uploads/legacy.rake create mode 100644 spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb create mode 100644 spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb diff --git a/changelogs/unreleased/50070-legacy-attachments.yml b/changelogs/unreleased/50070-legacy-attachments.yml new file mode 100644 index 00000000000..03f1cec0f67 --- /dev/null +++ b/changelogs/unreleased/50070-legacy-attachments.yml @@ -0,0 +1,5 @@ +--- +title: Create rake tasks for migrating legacy uploads out of deprecated paths +merge_request: 29409 +author: +type: other diff --git a/doc/administration/logs.md b/doc/administration/logs.md index 47abbc512e0..306d611f6bf 100644 --- a/doc/administration/logs.md +++ b/doc/administration/logs.md @@ -309,6 +309,12 @@ GraphQL queries are recorded in that file. For example: {"query_string":"query IntrospectionQuery{__schema {queryType { name },mutationType { name }}}...(etc)","variables":{"a":1,"b":2},"complexity":181,"depth":1,"duration":7} ``` +## `migrations.log` + +Introduced in GitLab 12.3. This file lives in `/var/log/gitlab/gitlab-rails/migrations.log` for +Omnibus GitLab packages or in `/home/git/gitlab/log/migrations.log` for +installations from source. + ## Reconfigure Logs Reconfigure log files live in `/var/log/gitlab/reconfigure` for Omnibus GitLab diff --git a/doc/administration/raketasks/uploads/migrate.md b/doc/administration/raketasks/uploads/migrate.md index fd8ea8d3162..86e8b763f51 100644 --- a/doc/administration/raketasks/uploads/migrate.md +++ b/doc/administration/raketasks/uploads/migrate.md @@ -103,3 +103,13 @@ sudo -u git -H bundle exec rake "gitlab:uploads:migrate[NamespaceFileUploader, S sudo -u git -H bundle exec rake "gitlab:uploads:migrate[FileUploader, MergeRequest]" ``` + +## Migrate legacy uploads out of deprecated paths + +> Introduced in GitLab 12.3. + +To migrate all uploads created by legacy uploaders, run: + +```shell +bundle exec rake gitlab:uploads:legacy:migrate +``` diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md index c97e179910b..67f36eb1ab4 100644 --- a/doc/development/rake_tasks.md +++ b/doc/development/rake_tasks.md @@ -216,3 +216,4 @@ bundle exec rake routes Since these take some time to create, it's often helpful to save the output to a file for quick reference. + diff --git a/lib/gitlab/background_migration/legacy_upload_mover.rb b/lib/gitlab/background_migration/legacy_upload_mover.rb new file mode 100644 index 00000000000..051c1176edb --- /dev/null +++ b/lib/gitlab/background_migration/legacy_upload_mover.rb @@ -0,0 +1,140 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # This class takes a legacy upload and migrates it to the correct location + class LegacyUploadMover + include Gitlab::Utils::StrongMemoize + + attr_reader :upload, :project, :note + attr_accessor :logger + + def initialize(upload) + @upload = upload + @note = Note.find_by(id: upload.model_id) + @project = note&.project + @logger = Gitlab::BackgroundMigration::Logger.build + end + + def execute + return unless upload + + if !project + # if we don't have models associated with the upload we can not move it + warn('Deleting upload due to model not found.') + + destroy_legacy_upload + elsif note.is_a?(LegacyDiffNote) + return unless move_legacy_diff_file + + migrate_upload + elsif !legacy_file_exists? + warn('Deleting upload due to file not found.') + destroy_legacy_upload + else + migrate_upload + end + end + + private + + def migrate_upload + return unless copy_upload_to_project + + add_upload_link_to_note_text + destroy_legacy_file + destroy_legacy_upload + end + + # we should proceed and log whenever one upload copy fails, no matter the reasons + # rubocop: disable Lint/RescueException + def copy_upload_to_project + @uploader = FileUploader.copy_to(legacy_file_uploader, project) + + logger.info( + message: 'MigrateLegacyUploads: File copied successfully', + old_path: legacy_file_uploader.file.path, new_path: @uploader.file.path + ) + true + rescue Exception => e + warn( + 'File could not be copied to project uploads', + file_path: legacy_file_uploader.file.path, error: e.message + ) + false + end + # rubocop: enable Lint/RescueException + + def destroy_legacy_upload + if note + note.remove_attachment = true + note.save + end + + if upload.destroy + logger.info(message: 'MigrateLegacyUploads: Upload was destroyed.', upload: upload.inspect) + else + warn('MigrateLegacyUploads: Upload destroy failed.') + end + end + + def destroy_legacy_file + legacy_file_uploader.file.delete + end + + def add_upload_link_to_note_text + new_text = "#{note.note} \n #{@uploader.markdown_link}" + # Bypass validations because old data may have invalid + # noteable values. If we fail hard here, we may kill the + # entire background migration, which affects a range of notes. + note.update_attribute(:note, new_text) + end + + def legacy_file_uploader + strong_memoize(:legacy_file_uploader) do + uploader = upload.build_uploader + uploader.retrieve_from_store!(File.basename(upload.path)) + uploader + end + end + + def legacy_file_exists? + legacy_file_uploader.file.exists? + end + + # we should proceed and log whenever one upload copy fails, no matter the reasons + # rubocop: disable Lint/RescueException + def move_legacy_diff_file + old_path = upload.absolute_path + old_path_sub = '-/system/note/attachment' + + if !File.exist?(old_path) || !old_path.include?(old_path_sub) + log_legacy_diff_note_problem(old_path) + return false + end + + new_path = upload.absolute_path.sub(old_path_sub, '-/system/legacy_diff_note/attachment') + new_dir = File.dirname(new_path) + FileUtils.mkdir_p(new_dir) + + FileUtils.mv(old_path, new_path) + rescue Exception => e + log_legacy_diff_note_problem(old_path, new_path, e) + false + end + + def warn(message, params = {}) + logger.warn( + params.merge(message: "MigrateLegacyUploads: #{message}", upload: upload.inspect) + ) + end + + def log_legacy_diff_note_problem(old_path, new_path = nil, error = nil) + warn('LegacyDiffNote upload could not be moved to a new path', + old_path: old_path, new_path: new_path, error: error&.message + ) + end + # rubocop: enable Lint/RescueException + end + end +end diff --git a/lib/gitlab/background_migration/legacy_uploads_migrator.rb b/lib/gitlab/background_migration/legacy_uploads_migrator.rb new file mode 100644 index 00000000000..a9d38a27e0c --- /dev/null +++ b/lib/gitlab/background_migration/legacy_uploads_migrator.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # This migration takes all legacy uploads (that were uploaded using AttachmentUploader) + # and migrate them to the new (FileUploader) location (=under projects). + # + # We have dependencies (uploaders) in this migration because extracting code would add a lot of complexity + # and possible errors could appear as the logic in the uploaders is not trivial. + # + # This migration will be removed in 13.0 in order to get rid of a migration that depends on + # the application code. + class LegacyUploadsMigrator + include Database::MigrationHelpers + + def perform(start_id, end_id) + Upload.where(id: start_id..end_id, uploader: 'AttachmentUploader').find_each do |upload| + LegacyUploadMover.new(upload).execute + end + end + end + end +end diff --git a/lib/gitlab/background_migration/logger.rb b/lib/gitlab/background_migration/logger.rb new file mode 100644 index 00000000000..4ea89771eff --- /dev/null +++ b/lib/gitlab/background_migration/logger.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # Logger that can be used for migrations logging + class Logger < ::Gitlab::JsonLogger + def self.file_name_noext + 'migrations' + end + end + end +end diff --git a/lib/tasks/gitlab/uploads/legacy.rake b/lib/tasks/gitlab/uploads/legacy.rake new file mode 100644 index 00000000000..18fb8afe455 --- /dev/null +++ b/lib/tasks/gitlab/uploads/legacy.rake @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +namespace :gitlab do + namespace :uploads do + namespace :legacy do + desc "GitLab | Uploads | Migrate all legacy attachments" + task migrate: :environment do + class Upload < ApplicationRecord + self.table_name = 'uploads' + + include ::EachBatch + end + + migration = 'LegacyUploadsMigrator'.freeze + batch_size = 5000 + delay_interval = 5.minutes.to_i + + Upload.where(uploader: 'AttachmentUploader').each_batch(of: batch_size) do |relation, index| + start_id, end_id = relation.pluck('MIN(id), MAX(id)').first + delay = index * delay_interval + + BackgroundMigrationWorker.perform_in(delay, migration, [start_id, end_id]) + end + end + end + end +end diff --git a/spec/factories/uploads.rb b/spec/factories/uploads.rb index 2ede92c8af0..3f6326114c9 100644 --- a/spec/factories/uploads.rb +++ b/spec/factories/uploads.rb @@ -56,10 +56,7 @@ FactoryBot.define do end trait :attachment_upload do - transient do - mount_point :attachment - end - + mount_point :attachment model { build(:note) } uploader "AttachmentUploader" end diff --git a/spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb b/spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb new file mode 100644 index 00000000000..7d67dc0251d --- /dev/null +++ b/spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb @@ -0,0 +1,296 @@ +# frozen_string_literal: true +require 'spec_helper' + +# rubocop: disable RSpec/FactoriesInMigrationSpecs +describe Gitlab::BackgroundMigration::LegacyUploadMover do + let(:test_dir) { FileUploader.options['storage_path'] } + let(:filename) { 'image.png' } + + let!(:namespace) { create(:namespace) } + let!(:legacy_project) { create(:project, :legacy_storage, namespace: namespace) } + let!(:hashed_project) { create(:project, namespace: namespace) } + # default project + let(:project) { legacy_project } + + let!(:issue) { create(:issue, project: project) } + let!(:note) { create(:note, note: 'some note', project: project, noteable: issue) } + + let(:legacy_upload) { create_upload(note, filename) } + + def create_remote_upload(model, filename) + create(:upload, :attachment_upload, + path: "note/attachment/#{model.id}/#{filename}", secret: nil, + store: ObjectStorage::Store::REMOTE, model: model) + end + + def create_upload(model, filename, with_file = true) + params = { + path: "uploads/-/system/note/attachment/#{model.id}/#{filename}", + model: model, + store: ObjectStorage::Store::LOCAL + } + + if with_file + upload = create(:upload, :with_file, :attachment_upload, params) + model.update(attachment: upload.build_uploader) + model.attachment.upload + else + create(:upload, :attachment_upload, params) + end + end + + def new_upload + Upload.find_by(model_id: project.id, model_type: 'Project') + end + + def expect_error_log + expect_next_instance_of(Gitlab::BackgroundMigration::Logger) do |logger| + expect(logger).to receive(:warn) + end + end + + shared_examples 'legacy upload deletion' do + it 'removes the upload record' do + described_class.new(legacy_upload).execute + + expect { legacy_upload.reload }.to raise_error(ActiveRecord::RecordNotFound) + end + end + + shared_examples 'move error' do + it 'does not remove the upload file' do + expect_error_log + + described_class.new(legacy_upload).execute + + expect(legacy_upload.reload).to eq(legacy_upload) + end + end + + shared_examples 'migrates the file correctly' do + before do + described_class.new(legacy_upload).execute + end + + it 'creates a new uplaod record correctly' do + expect(new_upload.secret).not_to be_nil + expect(new_upload.path).to end_with("#{new_upload.secret}/image.png") + expect(new_upload.model_id).to eq(project.id) + expect(new_upload.model_type).to eq('Project') + expect(new_upload.uploader).to eq('FileUploader') + end + + it 'updates the legacy upload note so that it references the file in the markdown' do + expected_path = File.join('/uploads', new_upload.secret, 'image.png') + expected_markdown = "some note \n ![image](#{expected_path})" + expect(note.reload.note).to eq(expected_markdown) + end + + it 'removes the attachment from the note model' do + expect(note.reload.attachment.file).to be_nil + end + end + + context 'when no model found for the upload' do + before do + legacy_upload.model = nil + expect_error_log + end + + it_behaves_like 'legacy upload deletion' + end + + context 'when the upload move fails' do + before do + expect(FileUploader).to receive(:copy_to).and_raise('failed') + end + + it_behaves_like 'move error' + end + + context 'when the upload is in local storage' do + shared_examples 'legacy local file' do + it 'removes the file correctly' do + expect(File.exist?(legacy_upload.absolute_path)).to be_truthy + + described_class.new(legacy_upload).execute + + expect(File.exist?(legacy_upload.absolute_path)).to be_falsey + end + + it 'moves legacy uploads to the correct location' do + described_class.new(legacy_upload).execute + + expected_path = File.join(test_dir, 'uploads', project.disk_path, new_upload.secret, filename) + expect(File.exist?(expected_path)).to be_truthy + end + end + + context 'when the upload file does not exist on the filesystem' do + let(:legacy_upload) { create_upload(note, filename, false) } + + before do + expect_error_log + end + + it_behaves_like 'legacy upload deletion' + end + + context 'when an upload belongs to a legacy_diff_note' do + let!(:merge_request) { create(:merge_request, source_project: project) } + let!(:note) do + create(:legacy_diff_note_on_merge_request, + note: 'some note', project: project, noteable: merge_request) + end + let(:legacy_upload) do + create(:upload, :with_file, :attachment_upload, + path: "uploads/-/system/note/attachment/#{note.id}/#{filename}", model: note) + end + + context 'when the file does not exist for the upload' do + let(:legacy_upload) do + create(:upload, :attachment_upload, + path: "uploads/-/system/note/attachment/#{note.id}/#{filename}", model: note) + end + + it_behaves_like 'move error' + end + + context 'when the file does not exist on expected path' do + let(:legacy_upload) do + create(:upload, :attachment_upload, :with_file, + path: "uploads/-/system/note/attachment/some_part/#{note.id}/#{filename}", model: note) + end + + it_behaves_like 'move error' + end + + context 'when the file path does not include system/note/attachment' do + let(:legacy_upload) do + create(:upload, :attachment_upload, :with_file, + path: "uploads/-/system#{note.id}/#{filename}", model: note) + end + + it_behaves_like 'move error' + end + + context 'when the file move raises an error' do + before do + allow(FileUtils).to receive(:mv).and_raise(Errno::EACCES) + end + + it_behaves_like 'move error' + end + + context 'when the file can be handled correctly' do + it_behaves_like 'migrates the file correctly' + it_behaves_like 'legacy local file' + it_behaves_like 'legacy upload deletion' + end + end + + context 'when object storage is disabled for FileUploader' do + context 'when the file belongs to a legacy project' do + let(:project) { legacy_project } + + it_behaves_like 'migrates the file correctly' + it_behaves_like 'legacy local file' + it_behaves_like 'legacy upload deletion' + end + + context 'when the file belongs to a hashed project' do + let(:project) { hashed_project } + + it_behaves_like 'migrates the file correctly' + it_behaves_like 'legacy local file' + it_behaves_like 'legacy upload deletion' + end + end + + context 'when object storage is enabled for FileUploader' do + # The process of migrating to object storage is a manual one, + # so it would go against expectations to automatically migrate these files + # to object storage during this migration. + # After this migration, these files should be able to successfully migrate to object storage. + + before do + stub_uploads_object_storage(FileUploader) + end + + context 'when the file belongs to a legacy project' do + let(:project) { legacy_project } + + it_behaves_like 'migrates the file correctly' + it_behaves_like 'legacy local file' + it_behaves_like 'legacy upload deletion' + end + + context 'when the file belongs to a hashed project' do + let(:project) { hashed_project } + + it_behaves_like 'migrates the file correctly' + it_behaves_like 'legacy local file' + it_behaves_like 'legacy upload deletion' + end + end + end + + context 'when legacy uploads are stored in object storage' do + let(:legacy_upload) { create_remote_upload(note, filename) } + let(:remote_file) do + { key: "#{legacy_upload.path}" } + end + let(:connection) { ::Fog::Storage.new(FileUploader.object_store_credentials) } + let(:bucket) { connection.directories.create(key: 'uploads') } + + before do + stub_uploads_object_storage(FileUploader) + end + + shared_examples 'legacy remote file' do + it 'removes the file correctly' do + # expect(bucket.files.get(remote_file[:key])).to be_nil + + described_class.new(legacy_upload).execute + + expect(bucket.files.get(remote_file[:key])).to be_nil + end + + it 'moves legacy uploads to the correct remote location' do + described_class.new(legacy_upload).execute + + connection = ::Fog::Storage.new(FileUploader.object_store_credentials) + expect(connection.get_object('uploads', new_upload.path)[:status]).to eq(200) + end + end + + context 'when the upload file does not exist on the filesystem' do + it_behaves_like 'legacy upload deletion' + end + + context 'when the file belongs to a legacy project' do + before do + bucket.files.create(remote_file) + end + + let(:project) { legacy_project } + + it_behaves_like 'migrates the file correctly' + it_behaves_like 'legacy remote file' + it_behaves_like 'legacy upload deletion' + end + + context 'when the file belongs to a hashed project' do + before do + bucket.files.create(remote_file) + end + + let(:project) { hashed_project } + + it_behaves_like 'migrates the file correctly' + it_behaves_like 'legacy remote file' + it_behaves_like 'legacy upload deletion' + end + end +end +# rubocop: enable RSpec/FactoriesInMigrationSpecs diff --git a/spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb b/spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb new file mode 100644 index 00000000000..ed8cbfeb11f --- /dev/null +++ b/spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true +require 'spec_helper' + +# rubocop: disable RSpec/FactoriesInMigrationSpecs +describe Gitlab::BackgroundMigration::LegacyUploadsMigrator do + let(:test_dir) { FileUploader.options['storage_path'] } + + let!(:hashed_project) { create(:project) } + let!(:legacy_project) { create(:project, :legacy_storage) } + let!(:issue) { create(:issue, project: hashed_project) } + let!(:issue_legacy) { create(:issue, project: legacy_project) } + + let!(:note1) { create(:note, project: hashed_project, noteable: issue) } + let!(:note2) { create(:note, project: hashed_project, noteable: issue) } + let!(:note_legacy) { create(:note, project: legacy_project, noteable: issue_legacy) } + + def create_upload(model, with_file = true) + filename = 'image.png' + params = { + path: "uploads/-/system/note/attachment/#{model.id}/#{filename}", + model: model, + store: ObjectStorage::Store::LOCAL + } + + if with_file + upload = create(:upload, :with_file, :attachment_upload, params) + model.update(attachment: upload.build_uploader) + model.attachment.upload + else + create(:upload, :attachment_upload, params) + end + end + + let!(:legacy_upload) { create_upload(note1) } + let!(:legacy_upload_no_file) { create_upload(note2, false) } + let!(:legacy_upload_legacy_project) { create_upload(note_legacy) } + + let(:start_id) { 1 } + let(:end_id) { 10000 } + + subject { described_class.new.perform(start_id, end_id) } + + it 'removes all legacy files' do + expect(File.exist?(legacy_upload.absolute_path)).to be_truthy + expect(File.exist?(legacy_upload_no_file.absolute_path)).to be_falsey + expect(File.exist?(legacy_upload_legacy_project.absolute_path)).to be_truthy + + subject + + expect(File.exist?(legacy_upload.absolute_path)).to be_falsey + expect(File.exist?(legacy_upload_no_file.absolute_path)).to be_falsey + expect(File.exist?(legacy_upload_legacy_project.absolute_path)).to be_falsey + end + + it 'removes all AttachmentUploader records' do + expect { subject }.to change { Upload.where(uploader: 'AttachmentUploader').count }.from(3).to(0) + end + + it 'creates new uploads for successfully migrated records' do + expect { subject }.to change { Upload.where(uploader: 'FileUploader').count }.from(0).to(2) + end +end +# rubocop: enable RSpec/FactoriesInMigrationSpecs -- cgit v1.2.1 From 01b2342292e34f15ae1e5b5d2f288043c8c0aef9 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Fri, 16 Aug 2019 06:34:55 +0000 Subject: Add feature specs for multiple group issue boards Add feature specs for multiple issue boards for groups --- spec/features/boards/multiple_boards_spec.rb | 15 +++ .../multiple_issue_boards_shared_examples.rb | 144 +++++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 spec/features/boards/multiple_boards_spec.rb create mode 100644 spec/support/shared_examples/boards/multiple_issue_boards_shared_examples.rb diff --git a/spec/features/boards/multiple_boards_spec.rb b/spec/features/boards/multiple_boards_spec.rb new file mode 100644 index 00000000000..9a2b7a80498 --- /dev/null +++ b/spec/features/boards/multiple_boards_spec.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'Multiple Issue Boards', :js do + set(:user) { create(:user) } + set(:project) { create(:project, :public) } + set(:planning) { create(:label, project: project, name: 'Planning') } + set(:board) { create(:board, name: 'board1', project: project) } + set(:board2) { create(:board, name: 'board2', project: project) } + let(:parent) { project } + let(:boards_path) { project_boards_path(project) } + + it_behaves_like 'multiple issue boards' +end diff --git a/spec/support/shared_examples/boards/multiple_issue_boards_shared_examples.rb b/spec/support/shared_examples/boards/multiple_issue_boards_shared_examples.rb new file mode 100644 index 00000000000..76d82649c5f --- /dev/null +++ b/spec/support/shared_examples/boards/multiple_issue_boards_shared_examples.rb @@ -0,0 +1,144 @@ +# frozen_string_literal: true + +shared_examples_for 'multiple issue boards' do + dropdown_selector = '.js-boards-selector .dropdown-menu' + + context 'authorized user' do + before do + parent.add_maintainer(user) + + login_as(user) + + visit boards_path + wait_for_requests + end + + it 'shows current board name' do + page.within('.boards-switcher') do + expect(page).to have_content(board.name) + end + end + + it 'shows a list of boards' do + click_button board.name + + page.within(dropdown_selector) do + expect(page).to have_content(board.name) + expect(page).to have_content(board2.name) + end + end + + it 'switches current board' do + click_button board.name + + page.within(dropdown_selector) do + click_link board2.name + end + + wait_for_requests + + page.within('.boards-switcher') do + expect(page).to have_content(board2.name) + end + end + + it 'creates new board without detailed configuration' do + click_button board.name + + page.within(dropdown_selector) do + click_button 'Create new board' + end + + fill_in 'board-new-name', with: 'This is a new board' + click_button 'Create board' + wait_for_requests + + expect(page).to have_button('This is a new board') + end + + it 'deletes board' do + click_button board.name + + wait_for_requests + + page.within(dropdown_selector) do + click_button 'Delete board' + end + + expect(page).to have_content('Are you sure you want to delete this board?') + click_button 'Delete' + + click_button board2.name + page.within(dropdown_selector) do + expect(page).not_to have_content(board.name) + expect(page).to have_content(board2.name) + end + end + + it 'adds a list to the none default board' do + click_button board.name + + page.within(dropdown_selector) do + click_link board2.name + end + + wait_for_requests + + page.within('.boards-switcher') do + expect(page).to have_content(board2.name) + end + + click_button 'Add list' + + wait_for_requests + + page.within '.dropdown-menu-issues-board-new' do + click_link planning.title + end + + wait_for_requests + + expect(page).to have_selector('.board', count: 3) + + click_button board2.name + + page.within(dropdown_selector) do + click_link board.name + end + + wait_for_requests + + expect(page).to have_selector('.board', count: 2) + end + + it 'maintains sidebar state over board switch' do + assert_boards_nav_active + + find('.boards-switcher').click + wait_for_requests + click_link board2.name + + assert_boards_nav_active + end + end + + context 'unauthorized user' do + before do + visit boards_path + wait_for_requests + end + + it 'does not show action links' do + click_button board.name + + page.within(dropdown_selector) do + expect(page).not_to have_content('Create new board') + expect(page).not_to have_content('Delete board') + end + end + end + + def assert_boards_nav_active + expect(find('.nav-sidebar .active .active')).to have_selector('a', text: 'Boards') + end +end -- cgit v1.2.1 From 094ab4b0947afedad1b9fe91b7a22e006b241487 Mon Sep 17 00:00:00 2001 From: Heinrich Lee Yu Date: Fri, 16 Aug 2019 08:48:54 +0000 Subject: Document cleanup of feature flag after deploy --- .gitlab/issue_templates/Feature Flag Roll Out.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab/issue_templates/Feature Flag Roll Out.md b/.gitlab/issue_templates/Feature Flag Roll Out.md index b7db5a33faf..0cac769bd55 100644 --- a/.gitlab/issue_templates/Feature Flag Roll Out.md +++ b/.gitlab/issue_templates/Feature Flag Roll Out.md @@ -39,5 +39,6 @@ If applicable, any groups/projects that are happy to have this feature turned on - [ ] Cross post chatops slack command to `#support_gitlab-com` and in your team channel - [ ] Announce on the issue that the flag has been enabled - [ ] Remove feature flag and add changelog entry +- [ ] After the flag removal is deployed, [clean up the feature flag](https://docs.gitlab.com/ee/development/feature_flags/controls.html#cleaning-up) by running chatops command in `#production` channel /label ~"feature flag" -- cgit v1.2.1 From 79bdb155b629fde0a68d8825759a40cfcfe215f6 Mon Sep 17 00:00:00 2001 From: Paul Slaughter Date: Fri, 16 Aug 2019 08:58:14 +0000 Subject: Rewrite changed_file_icon_spec in Jest - Uses vue-test-utils - More complete coverage with parameterized tests --- .../javascripts/ide/components/file_row_extra.vue | 1 - .../vue_shared/components/changed_file_icon.vue | 9 +- .../unreleased/61335-fix-file-icon-status.yml | 5 + .../components/changed_file_icon_spec.js | 123 +++++++++++++++++++++ .../components/changed_file_icon_spec.js | 63 ----------- 5 files changed, 129 insertions(+), 72 deletions(-) create mode 100644 changelogs/unreleased/61335-fix-file-icon-status.yml create mode 100644 spec/frontend/vue_shared/components/changed_file_icon_spec.js delete mode 100644 spec/javascripts/vue_shared/components/changed_file_icon_spec.js diff --git a/app/assets/javascripts/ide/components/file_row_extra.vue b/app/assets/javascripts/ide/components/file_row_extra.vue index 80a6ab9598a..7254c50a568 100644 --- a/app/assets/javascripts/ide/components/file_row_extra.vue +++ b/app/assets/javascripts/ide/components/file_row_extra.vue @@ -87,7 +87,6 @@ export default { :file="file" :show-tooltip="true" :show-staged-icon="true" - :force-modified-icon="true" /> diff --git a/changelogs/unreleased/61335-fix-file-icon-status.yml b/changelogs/unreleased/61335-fix-file-icon-status.yml new file mode 100644 index 00000000000..d524d91b246 --- /dev/null +++ b/changelogs/unreleased/61335-fix-file-icon-status.yml @@ -0,0 +1,5 @@ +--- +title: Fix IDE new files icon in tree +merge_request: 31560 +author: +type: fixed diff --git a/spec/frontend/vue_shared/components/changed_file_icon_spec.js b/spec/frontend/vue_shared/components/changed_file_icon_spec.js new file mode 100644 index 00000000000..806602877ef --- /dev/null +++ b/spec/frontend/vue_shared/components/changed_file_icon_spec.js @@ -0,0 +1,123 @@ +import { shallowMount } from '@vue/test-utils'; +import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue'; +import Icon from '~/vue_shared/components/icon.vue'; + +const changedFile = () => ({ changed: true }); +const stagedFile = () => ({ changed: false, staged: true }); +const changedAndStagedFile = () => ({ changed: true, staged: true }); +const newFile = () => ({ changed: true, tempFile: true }); +const unchangedFile = () => ({ changed: false, tempFile: false, staged: false, deleted: false }); + +describe('Changed file icon', () => { + let wrapper; + + const factory = (props = {}) => { + wrapper = shallowMount(ChangedFileIcon, { + propsData: { + file: changedFile(), + showTooltip: true, + ...props, + }, + sync: false, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + const findIcon = () => wrapper.find(Icon); + const findIconName = () => findIcon().props('name'); + const findIconClasses = () => + findIcon() + .props('cssClasses') + .split(' '); + const findTooltipText = () => wrapper.attributes('data-original-title'); + + it('with isCentered true, adds center class', () => { + factory({ + isCentered: true, + }); + + expect(wrapper.classes('ml-auto')).toBe(true); + }); + + it('with isCentered false, does not center', () => { + factory({ + isCentered: false, + }); + + expect(wrapper.classes('ml-auto')).toBe(false); + }); + + it('with showTooltip false, does not show tooltip', () => { + factory({ + showTooltip: false, + }); + + expect(findTooltipText()).toBeFalsy(); + }); + + describe.each` + file | iconName | tooltipText | desc + ${changedFile()} | ${'file-modified'} | ${'Unstaged modification'} | ${'with file changed'} + ${stagedFile()} | ${'file-modified-solid'} | ${'Staged modification'} | ${'with file staged'} + ${changedAndStagedFile()} | ${'file-modified'} | ${'Unstaged and staged modification'} | ${'with file changed and staged'} + ${newFile()} | ${'file-addition'} | ${'Unstaged addition'} | ${'with file new'} + `('$desc', ({ file, iconName, tooltipText }) => { + beforeEach(() => { + factory({ file }); + }); + + it('renders icon', () => { + expect(findIconName()).toBe(iconName); + expect(findIconClasses()).toContain(iconName); + }); + + it('renders tooltip text', () => { + expect(findTooltipText()).toBe(tooltipText); + }); + }); + + describe('with file unchanged', () => { + beforeEach(() => { + factory({ + file: unchangedFile(), + }); + }); + + it('does not show icon', () => { + expect(findIcon().exists()).toBe(false); + }); + + it('does not have tooltip text', () => { + expect(findTooltipText()).toBe(''); + }); + }); + + it('with size set, sets icon size', () => { + const size = 8; + + factory({ + file: changedFile(), + size, + }); + + expect(findIcon().props('size')).toBe(size); + }); + + // NOTE: It looks like 'showStagedIcon' behavior is backwards to what the name suggests + // https://gitlab.com/gitlab-org/gitlab-ce/issues/66071 + it.each` + showStagedIcon | iconName | desc + ${false} | ${'file-modified-solid'} | ${'with showStagedIcon false, renders staged icon'} + ${true} | ${'file-modified'} | ${'with showStagedIcon true, renders regular icon'} + `('$desc', ({ showStagedIcon, iconName }) => { + factory({ + file: stagedFile(), + showStagedIcon, + }); + + expect(findIconName()).toEqual(iconName); + }); +}); diff --git a/spec/javascripts/vue_shared/components/changed_file_icon_spec.js b/spec/javascripts/vue_shared/components/changed_file_icon_spec.js deleted file mode 100644 index 634ba8403d5..00000000000 --- a/spec/javascripts/vue_shared/components/changed_file_icon_spec.js +++ /dev/null @@ -1,63 +0,0 @@ -import Vue from 'vue'; -import changedFileIcon from '~/vue_shared/components/changed_file_icon.vue'; -import createComponent from 'spec/helpers/vue_mount_component_helper'; - -describe('Changed file icon', () => { - let vm; - - function factory(props = {}) { - const component = Vue.extend(changedFileIcon); - - vm = createComponent(component, { - ...props, - file: { - tempFile: false, - changed: true, - }, - }); - } - - afterEach(() => { - vm.$destroy(); - }); - - it('centers icon', () => { - factory({ - isCentered: true, - }); - - expect(vm.$el.classList).toContain('ml-auto'); - }); - - describe('changedIcon', () => { - it('equals file-modified when not a temp file and has changes', () => { - factory(); - - expect(vm.changedIcon).toBe('file-modified'); - }); - - it('equals file-addition when a temp file', () => { - factory(); - - vm.file.tempFile = true; - - expect(vm.changedIcon).toBe('file-addition'); - }); - }); - - describe('changedIconClass', () => { - it('includes file-modified when not a temp file', () => { - factory(); - - expect(vm.changedIconClass).toContain('file-modified'); - }); - - it('includes file-addition when a temp file', () => { - factory(); - - vm.file.tempFile = true; - - expect(vm.changedIconClass).toContain('file-addition'); - }); - }); -}); -- cgit v1.2.1 From 880c9a25a8738a4f4be26b147655b4cb6ac89d4e Mon Sep 17 00:00:00 2001 From: Steve Azzopardi Date: Thu, 25 Jul 2019 14:14:31 +0200 Subject: Update srmX configuration --- doc/user/gitlab_com/index.md | 83 ++++++++++---------------------------------- 1 file changed, 19 insertions(+), 64 deletions(-) diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md index c9fbd7effa0..d21a325d401 100644 --- a/doc/user/gitlab_com/index.md +++ b/doc/user/gitlab_com/index.md @@ -112,57 +112,6 @@ Below are the shared Runners settings. The full contents of our `config.toml` are: -**DigitalOcean** - -```toml -concurrent = X -check_interval = 1 -metrics_server = "X" -sentry_dsn = "X" - -[[runners]] - name = "docker-auto-scale" - request_concurrency = X - url = "https://gitlab.com/" - token = "SHARED_RUNNER_TOKEN" - executor = "docker+machine" - environment = [ - "DOCKER_DRIVER=overlay2" - ] - limit = X - [runners.docker] - image = "ruby:2.5" - privileged = true - [runners.machine] - IdleCount = 20 - IdleTime = 1800 - OffPeakPeriods = ["* * * * * sat,sun *"] - OffPeakTimezone = "UTC" - OffPeakIdleCount = 5 - OffPeakIdleTime = 1800 - MaxBuilds = 1 - MachineName = "srm-%s" - MachineDriver = "digitalocean" - MachineOptions = [ - "digitalocean-image=X", - "digitalocean-ssh-user=core", - "digitalocean-region=nyc1", - "digitalocean-size=s-2vcpu-2gb", - "digitalocean-private-networking", - "digitalocean-tags=shared_runners,gitlab_com", - "engine-registry-mirror=http://INTERNAL_IP_OF_OUR_REGISTRY_MIRROR", - "digitalocean-access-token=DIGITAL_OCEAN_ACCESS_TOKEN", - ] - [runners.cache] - Type = "s3" - BucketName = "runner" - Insecure = true - Shared = true - ServerAddress = "INTERNAL_IP_OF_OUR_CACHE_SERVER" - AccessKey = "ACCESS_KEY" - SecretKey = "ACCESS_SECRET_KEY" -``` - **Google Cloud Platform** ```toml @@ -178,20 +127,25 @@ sentry_dsn = "X" token = "SHARED_RUNNER_TOKEN" executor = "docker+machine" environment = [ - "DOCKER_DRIVER=overlay2" + "DOCKER_DRIVER=overlay2", + "DOCKER_TLS_CERTDIR=" ] limit = X [runners.docker] image = "ruby:2.5" privileged = true + volumes = [ + "/certs/client", + "/dummy-sys-class-dmi-id:/sys/class/dmi/id:ro" # Make kaniko builds work on GCP. + ] [runners.machine] - IdleCount = 20 - IdleTime = 1800 + IdleCount = 50 + IdleTime = 3600 OffPeakPeriods = ["* * * * * sat,sun *"] OffPeakTimezone = "UTC" - OffPeakIdleCount = 5 - OffPeakIdleTime = 1800 - MaxBuilds = 1 + OffPeakIdleCount = 15 + OffPeakIdleTime = 3600 + MaxBuilds = 1 # For security reasons we delete the VM after job has finished so it's not reused. MachineName = "srm-%s" MachineDriver = "google" MachineOptions = [ @@ -202,17 +156,18 @@ sentry_dsn = "X" "google-tags=gitlab-com,srm", "google-use-internal-ip", "google-zone=us-east1-d", + "engine-opt=mtu=1460", # Set MTU for container interface, for more information check https://gitlab.com/gitlab-org/gitlab-runner/issues/3214#note_82892928 "google-machine-image=PROJECT/global/images/IMAGE", - "engine-registry-mirror=http://INTERNAL_IP_OF_OUR_REGISTRY_MIRROR" + "engine-opt=ipv6", # This will create IPv6 interfaces in the containers. + "engine-opt=fixed-cidr-v6=fc00::/7", + "google-operation-backoff-initial-interval=2" # Custom flag from forked docker-machine, for more information check https://github.com/docker/machine/pull/4600 ] [runners.cache] - Type = "s3" - BucketName = "runner" - Insecure = true + Type = "gcs" Shared = true - ServerAddress = "INTERNAL_IP_OF_OUR_CACHE_SERVER" - AccessKey = "ACCESS_KEY" - SecretKey = "ACCESS_SECRET_KEY" + [runners.cache.gcs] + CredentialsFile = "/path/to/file" + BucketName = "bucket-name" ``` ## Sidekiq -- cgit v1.2.1 From afe4d3e5bb28a3c0de6e0885de4a45e1396e304f Mon Sep 17 00:00:00 2001 From: Marcel Amirault Date: Fri, 16 Aug 2019 12:06:00 +0000 Subject: Update docs style for code blocks Clarify rules for code blocks, including spaces above and below, and to use tilde when code blocks contain triple backticks --- doc/administration/integration/plantuml.md | 4 ++-- doc/development/documentation/styleguide.md | 22 ++++++++++++---------- doc/user/asciidoc.md | 4 ++-- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/doc/administration/integration/plantuml.md b/doc/administration/integration/plantuml.md index c2ac063ce37..16a193550a1 100644 --- a/doc/administration/integration/plantuml.md +++ b/doc/administration/integration/plantuml.md @@ -72,12 +72,12 @@ our AsciiDoc snippets, wikis and repos using delimited blocks: - **Markdown** - ````markdown + ~~~markdown ```plantuml Bob -> Alice : hello Alice -> Bob : Go Away ``` - ```` + ~~~ - **AsciiDoc** diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md index 680f2cd13c2..c1e3eb9680b 100644 --- a/doc/development/documentation/styleguide.md +++ b/doc/development/documentation/styleguide.md @@ -655,15 +655,16 @@ nicely on different mobile devices. ## Code blocks -- Always wrap code added to a sentence in inline code blocks (``` ` ```). +- Always wrap code added to a sentence in inline code blocks (`` ` ``). E.g., `.gitlab-ci.yml`, `git add .`, `CODEOWNERS`, `only: master`. File names, commands, entries, and anything that refers to code should be added to code blocks. To make things easier for the user, always add a full code block for things that can be useful to copy and paste, as they can easily do it with the button on code blocks. +- Add a blank line above and below code blocks. - For regular code blocks, always use a highlighting class corresponding to the language for better readability. Examples: - ````md + ~~~md ```ruby Ruby code ``` @@ -673,16 +674,17 @@ nicely on different mobile devices. ``` ```md - Markdown code + [Markdown code example](example.md) ``` ```text - Code for which no specific highlighting class is available. + Code or text for which no specific highlighting class is available. ``` - ```` + ~~~ -- To display raw markdown instead of rendered markdown, use four backticks on their own lines around the - markdown to display. See [example](https://gitlab.com/gitlab-org/gitlab-ce/blob/8c1991b9bb7e3b8d606481fdea316d633cfa5eb7/doc/development/documentation/styleguide.md#L275-287). +- To display raw markdown instead of rendered markdown, you can use triple backticks + with `md`, like the `Markdown code` example above, unless you want to include triple + backticks in the code block as well. In that case, use triple tildes (`~~~`) instead. - For a complete reference on code blocks, check the [Kramdown guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/#code-blocks). ## Alert boxes @@ -1024,7 +1026,7 @@ on this document. Further explanation is given below. The following can be used as a template to get started: -````md +~~~md ## Descriptive title One or two sentence description of what endpoint does. @@ -1052,7 +1054,7 @@ Example response: } ] ``` -```` +~~~ ### Fake tokens @@ -1080,7 +1082,7 @@ You can use the following fake tokens as examples. ### Method description Use the following table headers to describe the methods. Attributes should -always be in code blocks using backticks (``` ` ```). +always be in code blocks using backticks (`` ` ``). ```md | Attribute | Type | Required | Description | diff --git a/doc/user/asciidoc.md b/doc/user/asciidoc.md index df86b2a1cbe..862316b57da 100644 --- a/doc/user/asciidoc.md +++ b/doc/user/asciidoc.md @@ -277,11 +277,11 @@ source - a listing that is embellished with (colorized) syntax highlighting ---- ``` -````asciidoc +~~~asciidoc \```language fenced code - a shorthand syntax for the source block \``` -```` +~~~ ```asciidoc [,attribution,citetitle] -- cgit v1.2.1 From f4632f3a0462522fe2cf79384303cf5c10600be8 Mon Sep 17 00:00:00 2001 From: Marcel Amirault Date: Fri, 16 Aug 2019 12:07:42 +0000 Subject: Adjust headers in /university --- doc/topics/autodevops/index.md | 10 +-- doc/university/training/end-user/README.md | 81 +--------------------- doc/university/training/topics/bisect.md | 4 +- doc/university/training/topics/cherry_picking.md | 6 +- .../training/topics/feature_branching.md | 4 +- doc/university/training/topics/getting_started.md | 4 -- doc/university/training/topics/git_add.md | 4 -- doc/university/training/topics/merge_conflicts.md | 4 +- doc/university/training/topics/merge_requests.md | 2 - doc/university/training/topics/stash.md | 6 +- doc/university/training/topics/tags.md | 12 ++-- doc/university/training/topics/unstage.md | 2 - 12 files changed, 18 insertions(+), 121 deletions(-) diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md index 95220d6364c..9c1258fa1aa 100644 --- a/doc/topics/autodevops/index.md +++ b/doc/topics/autodevops/index.md @@ -816,7 +816,7 @@ To configure your application variables: 1. Create a CI Variable, ensuring the key is prefixed with `K8S_SECRET_`. For example, you can create a variable with key -`K8S_SECRET_RAILS_MASTER_KEY`. + `K8S_SECRET_RAILS_MASTER_KEY`. 1. Run an Auto Devops pipeline either by manually creating a new pipeline or by pushing a code change to GitLab. @@ -1017,10 +1017,10 @@ Everything behaves the same way, except: - It's enabled by setting the `INCREMENTAL_ROLLOUT_MODE` variable to `timed`. - Instead of the standard `production` job, the following jobs with a 5 minute delay between each are created: - 1. `timed rollout 10%` - 1. `timed rollout 25%` - 1. `timed rollout 50%` - 1. `timed rollout 100%` + 1. `timed rollout 10%` + 1. `timed rollout 25%` + 1. `timed rollout 50%` + 1. `timed rollout 100%` ## Currently supported languages diff --git a/doc/university/training/end-user/README.md b/doc/university/training/end-user/README.md index 423ba1cfbd7..1218465c87a 100644 --- a/doc/university/training/end-user/README.md +++ b/doc/university/training/end-user/README.md @@ -9,12 +9,8 @@ which can be found at [End User Slides](https://gitlab-org.gitlab.io/end-user-tr through it's [RevealJS](https://gitlab.com/gitlab-org/end-user-training-slides) project. ---- - ## Git Intro ---- - ### What is a Version Control System (VCS) - Records changes to a file @@ -22,8 +18,6 @@ project. - Disaster Recovery - Types of VCS: Local, Centralized and Distributed ---- - ### Short Story of Git - 1991-2002: The Linux kernel was being maintained by sharing archived files @@ -31,8 +25,6 @@ project. - 2002: The Linux kernel project began using a DVCS called BitKeeper - 2005: BitKeeper revoked the free-of-charge status and Git was created ---- - ### What is Git - Distributed Version Control System @@ -42,8 +34,6 @@ project. - Disaster recovery friendly - Open Source ---- - ### Getting Help - Use the tools at your disposal when you get stuck. @@ -51,14 +41,10 @@ project. - Use Google (i.e. StackOverflow, Google groups) - Read documentation at ---- - ## Git Setup Workshop Time! ---- - ### Setup - Windows: Install 'Git for Windows' @@ -69,8 +55,6 @@ Workshop Time! - Debian: `sudo apt-get install git-all` - Red Hat `sudo yum install git-all` ---- - ### Configure - One-time configuration of the Git client: @@ -91,16 +75,12 @@ git config --global --list - You might want or be required to use an SSH key. - Instructions: [SSH](http://doc.gitlab.com/ce/ssh/README.html) ---- - ### Workspace - Choose a directory on you machine easy to access - Create a workspace or development directory - This is where we'll be working and adding content ---- - ```bash mkdir ~/development cd ~/development @@ -111,12 +91,8 @@ mkdir ~/workspace cd ~/workspace ``` ---- - ## Git Basics ---- - ### Git Workflow - Untracked files @@ -128,8 +104,6 @@ cd ~/workspace - Upstream - Hosted repository on a shared server ---- - ### GitLab - GitLab is an application to code, test and deploy. @@ -137,8 +111,6 @@ cd ~/workspace issue tracking, Merge Requests, and other features. - The hosted version of GitLab is gitlab.com ---- - ### New Project - Sign in into your gitlab.com account @@ -146,8 +118,6 @@ cd ~/workspace - Choose to import from 'Any Repo by URL' and use - On your machine clone the `training-examples` project ---- - ### Git and GitLab basics 1. Edit `edit_this_file.rb` in `training-examples` @@ -158,8 +128,6 @@ cd ~/workspace 1. Push the commit to the remote 1. View the git log ---- - ```shell # Edit `edit_this_file.rb` git status @@ -170,8 +138,6 @@ git push origin master git log ``` ---- - ### Feature Branching 1. Create a new feature branch called `squash_some_bugs` @@ -179,8 +145,6 @@ git log 1. Commit 1. Push ---- - ```shell git checkout -b squash_some_bugs # Edit `bugs.rb` @@ -190,14 +154,8 @@ git commit -m 'Fix some buggy code' git push origin squash_some_bugs ``` ---- - ## Merge Request ---- - -### Merge requests - - When you want feedback create a merge request - Target is the ‘default’ branch (usually master) - Assign or mention the person you would like to review @@ -206,8 +164,6 @@ git push origin squash_some_bugs - Anyone can comment, not just the assignee - Push corrections to the same branch ---- - ### Merge request example - Create your first merge request @@ -216,8 +172,6 @@ git push origin squash_some_bugs - Push a new commit to the same branch - Review the changes again and notice the update ---- - ### Feedback and Collaboration - Merge requests are a time for feedback and collaboration @@ -230,24 +184,17 @@ git push origin squash_some_bugs --- -- Review the Thoughtbot code-review guide for suggestions to follow when reviewing merge requests:[Thoughtbot](https://github.com/thoughtbot/guides/tree/master/code-review) +- Review the Thoughtbot code-review guide for suggestions to follow when reviewing merge requests: + [Thoughtbot](https://github.com/thoughtbot/guides/tree/master/code-review) - See GitLab merge requests for examples: [Merge Requests](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests) ---- - ## Merge Conflicts ---- - -### Merge Conflicts - - Happen often - Learning to fix conflicts is hard - Practice makes perfect - Force push after fixing conflicts. Be careful! ---- - ### Example Plan 1. Checkout a new branch and edit conflicts.rb. Add 'Line4' and 'Line5'. @@ -261,8 +208,6 @@ git push origin squash_some_bugs 1. Force push the changes 1. Finally continue with the Merge Request ---- - ### Example 1/2 ```sh @@ -282,8 +227,6 @@ git commit -am "add line6 and line7" git push origin master ``` ---- - ### Example 2/2 Create a merge request on the GitLab web UI. You'll see a conflict warning. @@ -305,8 +248,6 @@ git rebase --continue git push origin conflicts_branch -f ``` ---- - ### Notes - When to use `git merge` and when to use `git rebase` @@ -314,12 +255,8 @@ git push origin conflicts_branch -f - Merge when bringing changes from feature to master - Reference: ---- - ## Revert and Unstage ---- - ### Unstage To remove files from stage use reset HEAD. Where HEAD is the last commit of the current branch: @@ -347,8 +284,6 @@ If we want to remove a file from the repository but keep it on disk, say we forg git rm --cache ``` ---- - ### Undo Commits Undo last commit putting everything back into the staging area: @@ -377,8 +312,6 @@ git reset --hard HEAD^^ Don't reset after pushing ---- - ### Reset Workflow 1. Edit file again 'edit_this_file.rb' @@ -392,8 +325,6 @@ Don't reset after pushing 1. Pull for updates 1. Push changes ---- - ```sh # Change file edit_this_file.rb git status @@ -407,8 +338,6 @@ git pull origin master git push origin master ``` ---- - ### git revert vs git reset Reset removes the commit while revert removes the changes but leaves the commit @@ -425,16 +354,10 @@ git revert # reverted commit is back (new commit created again) ``` ---- - ## Questions ---- - ## Instructor Notes ---- - ### Version Control - Local VCS was used with a filesystem or a simple db. diff --git a/doc/university/training/topics/bisect.md b/doc/university/training/topics/bisect.md index 4178afa2086..24dc670d9d5 100644 --- a/doc/university/training/topics/bisect.md +++ b/doc/university/training/topics/bisect.md @@ -4,13 +4,11 @@ comments: false # Bisect -## Bisect - - Find a commit that introduced a bug - Works through a process of elimination - Specify a known good and bad revision to begin -## Bisect +## Bisect sample workflow 1. Start the bisect process 1. Enter the bad revision (usually latest commit) diff --git a/doc/university/training/topics/cherry_picking.md b/doc/university/training/topics/cherry_picking.md index fa0cb5fe6a4..f5bcdfcbf12 100644 --- a/doc/university/training/topics/cherry_picking.md +++ b/doc/university/training/topics/cherry_picking.md @@ -4,13 +4,11 @@ comments: false # Cherry Pick -## Cherry Pick - - Given an existing commit on one branch, apply the change to another branch - Useful for backporting bug fixes to previous release branches - Make the commit on the master branch and pick in to stable -## Cherry Pick +## Cherry Pick sample workflow 1. Check out a new 'stable' branch from 'master' 1. Change back to 'master' @@ -19,8 +17,6 @@ comments: false 1. Check out the 'stable' branch 1. Cherry pick the commit using the SHA obtained earlier -## Commands - ```bash git checkout master git checkout -b stable diff --git a/doc/university/training/topics/feature_branching.md b/doc/university/training/topics/feature_branching.md index d2efe634533..f530389d4da 100644 --- a/doc/university/training/topics/feature_branching.md +++ b/doc/university/training/topics/feature_branching.md @@ -11,15 +11,13 @@ comments: false - Push branches to the server frequently - Hint: This is a cheap backup for your work-in-progress code -## Feature branching +## Feature branching sample workflow 1. Create a new feature branch called 'squash_some_bugs' 1. Edit '`bugs.rb`' and remove all the bugs. 1. Commit 1. Push -## Commands - ```sh git checkout -b squash_some_bugs # Edit `bugs.rb` diff --git a/doc/university/training/topics/getting_started.md b/doc/university/training/topics/getting_started.md index e8ff7916590..3fadb58e804 100644 --- a/doc/university/training/topics/getting_started.md +++ b/doc/university/training/topics/getting_started.md @@ -35,8 +35,6 @@ comments: false 1. Create a '`Workspace`' directory in your home directory. 1. Clone the '`training-examples`' project. -## Commands - ```sh mkdir ~/workspace cd ~/workspace @@ -69,8 +67,6 @@ Modified files that have been marked to go in the next commit. 1. Push the commit to the remote 1. View the git log -## Commands - ```sh # Edit `edit_this_file.rb` git status diff --git a/doc/university/training/topics/git_add.md b/doc/university/training/topics/git_add.md index 7152fc2030b..0c9a50bb5e1 100644 --- a/doc/university/training/topics/git_add.md +++ b/doc/university/training/topics/git_add.md @@ -4,8 +4,6 @@ comments: false # Git Add -## Git Add - Adds content to the index or staging area. - Adds a list of file: @@ -20,8 +18,6 @@ Adds content to the index or staging area. git add -A ``` -## Git add continued - - Add all text files in current dir: ```bash diff --git a/doc/university/training/topics/merge_conflicts.md b/doc/university/training/topics/merge_conflicts.md index dd235fe3a81..97bb038f405 100644 --- a/doc/university/training/topics/merge_conflicts.md +++ b/doc/university/training/topics/merge_conflicts.md @@ -9,7 +9,7 @@ comments: false - Practice makes perfect - Force push after fixing conflicts. Be careful! -## Merge conflicts +## Merge conflicts sample workflow 1. Checkout a new branch and edit `conflicts.rb`. Add 'Line4' and 'Line5'. 1. Commit and push. @@ -22,8 +22,6 @@ comments: false 1. Force push the changes. 1. Finally continue with the Merge Request. -## Commands - ```sh git checkout -b conflicts_branch diff --git a/doc/university/training/topics/merge_requests.md b/doc/university/training/topics/merge_requests.md index b5bbe7b2e1e..656871ae5b2 100644 --- a/doc/university/training/topics/merge_requests.md +++ b/doc/university/training/topics/merge_requests.md @@ -30,8 +30,6 @@ comments: false - Be as receptive as possible - Feedback is about the best code, not the person. You are not your code -## Feedback and Collaboration - Review the Thoughtbot code-review guide for suggestions to follow when reviewing merge requests: [https://github.com/thoughtbot/guides/tree/master/code-review](https://github.com/thoughtbot/guides/tree/master/code-review) diff --git a/doc/university/training/topics/stash.md b/doc/university/training/topics/stash.md index 21abad88cfa..d3e63db0c6a 100644 --- a/doc/university/training/topics/stash.md +++ b/doc/university/training/topics/stash.md @@ -25,7 +25,7 @@ and we need to change to a different branch. git stash apply stash@{3} ``` -- Every time we save a stash it gets stacked so by using list we can see all our +- Every time we save a stash it gets stacked so by using `list` we can see all our stashes. ```sh @@ -54,7 +54,7 @@ and we need to change to a different branch. - If we meet conflicts we need to either reset or commit our changes. - Conflicts through `pop` will not drop a stash afterwards. -## Git Stash +## Git Stash sample workflow 1. Modify a file 1. Stage file @@ -64,8 +64,6 @@ and we need to change to a different branch. 1. Apply with pop 1. View list to confirm changes -## Commands - ```sh # Modify edit_this_file.rb file git add . diff --git a/doc/university/training/topics/tags.md b/doc/university/training/topics/tags.md index cdbb8a2da7c..631b93cc384 100644 --- a/doc/university/training/topics/tags.md +++ b/doc/university/training/topics/tags.md @@ -11,18 +11,12 @@ type: reference - Many projects combine an annotated release tag with a stable branch - Consider setting deployment/release tags automatically -# Tags +## Tags sample workflow - Create a lightweight tag - Create an annotated tag - Push the tags to the remote repository -**Additional resources** - - - -# Commands - ```sh git checkout master @@ -36,6 +30,10 @@ git tag git push origin --tags ``` +**Additional resources** + + + -