Commit 020d6d06 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 0b84eb56fc72
......@@ -85,7 +85,7 @@ review-build-cng:
variables:
HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}"
DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}"
GITLAB_HELM_CHART_REF: "v2.6.8"
GITLAB_HELM_CHART_REF: "v3.2.2"
GITLAB_EDITION: "ce"
environment:
name: review/${CI_COMMIT_REF_NAME}
......
......@@ -25,13 +25,6 @@ Please provide pros/cons and a weight estimate for each solution.
- [ ] All potential solutions are listed.
- [ ] A solution has been chosen for the first iteration: `PUT THE CHOSEN SOLUTION HERE`
## Who and when will the solution be implemented?
<!--
For history reason, please list the person that will implement the solution and
the planned milestone/date.
-->
## Verify that the solution has improved the situation
<!--
......
......@@ -21,6 +21,8 @@ export default {
},
false,
),
goToTrackValue: 10,
trackEvent: 'click_button',
components: {
GlModal,
GlSprintf,
......@@ -43,12 +45,17 @@ export default {
},
data() {
return {
tracking: {
label: 'congratulate_first_pipeline',
property: this.humanAccess,
},
trackLabel: 'congratulate_first_pipeline',
};
},
computed: {
tracking() {
return {
label: this.trackLabel,
property: this.humanAccess,
};
},
},
mounted() {
this.track();
this.disableModalFromRenderingAgain();
......@@ -89,7 +96,17 @@ export default {
</template>
</gl-sprintf>
<template #modal-footer>
<a :href="goToPipelinesPath" class="btn btn-success">{{ __('Go to Pipelines') }}</a>
<a
ref="goto"
:href="goToPipelinesPath"
class="btn btn-success"
:data-track-property="humanAccess"
:data-track-value="$options.goToTrackValue"
:data-track-event="$options.trackEvent"
:data-track-label="trackLabel"
>
{{ __('Go to Pipelines') }}
</a>
</template>
</gl-modal>
</template>
......@@ -9,8 +9,10 @@ const getSvgDom = memoize(() =>
axios
.get(gon.sprite_icons)
.then(({ data: svgs }) => new DOMParser().parseFromString(svgs, 'text/xml'))
.catch(() => {
.catch(e => {
getSvgDom.cache.clear();
throw e;
}),
);
......
import initStaticSiteEditor from '~/static_site_editor';
window.addEventListener('DOMContentLoaded', () => {
initStaticSiteEditor(document.querySelector('#static-site-editor'));
});
import Vue from 'vue';
import StaticSiteEditor from './components/static_site_editor.vue';
import createStore from './store';
const initStaticSiteEditor = el => {
const store = createStore();
return new Vue({
el,
store,
components: {
StaticSiteEditor,
},
render(createElement) {
return createElement('static-site-editor', StaticSiteEditor);
},
});
};
export default initStaticSiteEditor;
import Vuex from 'vuex';
import Vue from 'vue';
import createState from './state';
Vue.use(Vuex);
const createStore = ({ initialState } = {}) => {
return new Vuex.Store({
state: createState(initialState),
});
};
export default createStore;
const createState = (initialState = {}) => ({
content: '',
...initialState,
});
export default createState;
......@@ -470,7 +470,6 @@ def higher_access_level_than_group
# for a Member to be commited before attempting to update the highest role.
# rubocop: disable CodeReuse/ServiceClass
def update_highest_role
return unless Feature.enabled?(:highest_role_callback)
return unless user_id.present?
return unless previous_changes[:access_level].present?
......
......@@ -237,6 +237,7 @@ def update_tracked_fields!(request)
end
end
end
after_commit :update_highest_role, on: [:create, :update]
after_initialize :set_projects_limit
......@@ -1844,6 +1845,21 @@ def groups_with_developer_maintainer_project_access
def no_recent_activity?
last_active_at.to_i <= MINIMUM_INACTIVE_DAYS.days.ago.to_i
end
# Triggers the service to schedule a Sidekiq job to update the highest role
# for a User
#
# The job will be called outside of a transaction in order to ensure the changes
# for a Member to be commited before attempting to update the highest role.
# rubocop: disable CodeReuse/ServiceClass
def update_highest_role
return unless (previous_changes.keys & %w(state user_type ghost)).any?
run_after_commit_or_now do
Members::UpdateHighestRoleService.new(id).execute
end
end
# rubocop: enable CodeReuse/ServiceClass
end
User.prepend_if_ee('EE::User')
......@@ -4,7 +4,8 @@ module Members
class UpdateHighestRoleService < ::BaseService
include ExclusiveLeaseGuard
LEASE_TIMEOUT = 30.minutes.to_i
LEASE_TIMEOUT = 10.minutes.to_i
DELAY = 10.minutes
attr_reader :user_id
......@@ -14,7 +15,7 @@ def initialize(user_id)
def execute
try_obtain_lease do
UpdateHighestRoleWorker.perform_async(user_id)
UpdateHighestRoleWorker.perform_in(DELAY, user_id)
end
end
......
......@@ -52,7 +52,7 @@ def save_and_commit(snippet)
create_commit(snippet) if snippet.repository_exists?
end
rescue => e
snippet.errors.add(:repository, 'Error updating the snippet')
snippet.errors.add(:repository, e.message)
log_error(e.message)
false
......
......@@ -2,7 +2,7 @@
module Users
class UpdateHighestMemberRoleService < BaseService
attr_reader :user, :identity_params
attr_reader :user
def initialize(user)
@user = user
......
......@@ -11,9 +11,15 @@ class UpdateHighestRoleWorker
# rubocop: disable CodeReuse/ActiveRecord
def perform(user_id)
user = User.active.find_by(id: user_id)
user = User.find_by(id: user_id)
Users::UpdateHighestMemberRoleService.new(user).execute if user.present?
return unless user.present?
if user.active? && user.user_type.nil? && !user.internal?
Users::UpdateHighestMemberRoleService.new(user).execute
else
UserHighestRole.where(user_id: user_id).delete_all
end
end
# rubocop: enable CodeReuse/ActiveRecord
end
---
title: Show snippet error update to the user
merge_request: 28516
author:
type: changed
---
title: Populate user_highest_roles table
merge_request: 27127
author:
type: added
---
title: Update user's highest role to keep the users statistics up to date
merge_request: 28087
author:
type: added
# frozen_string_literal: true
# See https://docs.gitlab.com/ee/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddMigratingUserHighestRolesTableIndexToUsers < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
INDEX_NAME = 'index_for_migrating_user_highest_roles_table'
disable_ddl_transaction!
def up
add_concurrent_index :users,
:id,
where: "state = 'active' AND user_type IS NULL AND bot_type IS NULL AND ghost IS NOT TRUE",
name: INDEX_NAME
end
def down
remove_concurrent_index :users, :id, name: INDEX_NAME
end
end
# frozen_string_literal: true
class SchedulePopulateUserHighestRolesTable < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
BATCH_SIZE = 10_000
DELAY = 5.minutes.to_i
DOWNTIME = false
MIGRATION = 'PopulateUserHighestRolesTable'
disable_ddl_transaction!
class User < ActiveRecord::Base
include EachBatch
scope :active, -> {
where(state: 'active', user_type: nil, bot_type: nil)
.where('ghost IS NOT TRUE')
}
end
def up
# We currently have ~5_300_000 users with the state active on GitLab.com.
# This means it'll schedule ~530 jobs (10k Users each) with a 5 minutes gap,
# so this should take ~44 hours for all background migrations to complete.
User.active.each_batch(of: BATCH_SIZE) do |batch, index|
range = batch.pluck(Arel.sql('MIN(id)'), Arel.sql('MAX(id)')).first
delay = index * DELAY
migrate_in(delay.seconds, MIGRATION, [*range])
end
end
def down
# nothing
end
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment