Skip to content
Snippets Groups Projects
Commit a77db6bc authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 6cf6996f
No related branches found
No related tags found
No related merge requests found
Showing
with 163 additions and 41 deletions
<script>
import _ from 'underscore';
import { mapState } from 'vuex';
import { GlTooltipDirective } from '@gitlab/ui';
import { sprintf, __ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
Loading
Loading
@@ -63,6 +64,7 @@ export default {
};
},
computed: {
...mapState(['isShowingLabels']),
numberOverLimit() {
return this.issue.assignees.length - this.limitBeforeCounter;
},
Loading
Loading
@@ -92,7 +94,7 @@ export default {
return false;
},
showLabelFooter() {
return this.issue.labels.find(l => this.showLabel(l)) !== undefined;
return this.isShowingLabels && this.issue.labels.find(this.showLabel);
},
issueReferencePath() {
const { referencePath, groupId } = this.issue;
Loading
Loading
Loading
Loading
@@ -13,6 +13,7 @@ import 'ee_else_ce/boards/models/issue';
import 'ee_else_ce/boards/models/list';
import '~/boards/models/milestone';
import '~/boards/models/project';
import store from '~/boards/stores';
import boardsStore from '~/boards/stores/boards_store';
import ModalStore from '~/boards/stores/modal_store';
import BoardService from 'ee_else_ce/boards/services/board_service';
Loading
Loading
@@ -29,6 +30,7 @@ import {
} from '~/lib/utils/common_utils';
import boardConfigToggle from 'ee_else_ce/boards/config_toggle';
import toggleFocusMode from 'ee_else_ce/boards/toggle_focus';
import toggleLabels from 'ee_else_ce/boards/toggle_labels';
import {
setPromotionState,
setWeigthFetchingState,
Loading
Loading
@@ -67,6 +69,7 @@ export default () => {
BoardSidebar,
BoardAddIssuesModal,
},
store,
data: {
state: boardsStore.state,
loading: true,
Loading
Loading
@@ -314,5 +317,6 @@ export default () => {
}
 
toggleFocusMode(ModalStore, boardsStore, $boardApp);
toggleLabels();
mountMultipleBoardsSwitcher();
};
export default {
getLabelToggleState: state => (state.isShowingLabels ? 'on' : 'off'),
};
import Vue from 'vue';
import Vuex from 'vuex';
import state from 'ee_else_ce/boards/stores/state';
import getters from 'ee_else_ce/boards/stores/getters';
import actions from 'ee_else_ce/boards/stores/actions';
import mutations from 'ee_else_ce/boards/stores/mutations';
 
Vue.use(Vuex);
 
export default () =>
export const createStore = () =>
new Vuex.Store({
state,
getters,
actions,
mutations,
});
export default createStore();
export default () => ({
// ...
isShowingLabels: true,
});
export default () => {};
Loading
Loading
@@ -545,3 +545,15 @@
.board-issue-path.js-show-tooltip {
cursor: help;
}
.board-labels-toggle-wrapper {
/**
* Make the wrapper the same height as a button so it aligns properly when the
* filtered-search-box input element increases in size on Linux smaller breakpoints
*/
height: 34px;
@include media-breakpoint-down(sm) {
margin-bottom: 10px;
}
}
Loading
Loading
@@ -9,25 +9,11 @@ module Projects
tag_names = params[:tags]
return error('not tags specified') if tag_names.blank?
 
if can_use?
smart_delete(container_repository, tag_names)
else
unsafe_delete(container_repository, tag_names)
end
smart_delete(container_repository, tag_names)
end
 
private
 
def unsafe_delete(container_repository, tag_names)
deleted_tags = tag_names.select do |tag_name|
container_repository.tag(tag_name).unsafe_delete
end
return error('could not delete tags') if deleted_tags.empty?
success(deleted: deleted_tags)
end
# Replace a tag on the registry with a dummy tag.
# This is a hack as the registry doesn't support deleting individual
# tags. This code effectively pushes a dummy image and assigns the tag to it.
Loading
Loading
@@ -57,10 +43,6 @@ module Projects
error('could not delete tags')
end
end
def can_use?
Feature.enabled?(:container_registry_smart_delete, project, default_enabled: true)
end
end
end
end
Loading
Loading
@@ -94,7 +94,8 @@
- else
= f.text_field :name, label: s_('Profiles|Full name'), required: true, title: s_("Profiles|Using emojis in names seems fun, but please try to set a status message instead"), wrapper: { class: 'col-md-9 qa-full-name rspec-full-name' }, help: s_("Profiles|Enter your name, so people you know can recognize you")
= f.text_field :id, readonly: true, label: s_('Profiles|User ID'), wrapper: { class: 'col-md-3' }
= f.select :role, ::User.roles.keys.map { |role| [role.titleize, role] }, {}, class: 'input-md'
- if experiment_enabled?(:signup_flow)
= f.select :role, ::User.roles.keys.map { |role| [role.titleize, role] }, { prompt: _('Select your role') }, class: 'input-md'
 
= render_if_exists 'profiles/email_settings', form: f
= f.text_field :skype, class: 'input-md', placeholder: s_("Profiles|username")
Loading
Loading
Loading
Loading
@@ -147,6 +147,7 @@
 
%button.clear-search.hidden{ type: 'button' }
= icon('times')
#js-board-labels-toggle
.filter-dropdown-container.d-flex.flex-column.flex-md-row
- if type == :boards
.js-board-config{ data: { can_admin_list: user_can_admin_list, has_scope: board.scoped? } }
Loading
Loading
---
title: Adds a Sidekiq queue duration metric
merge_request: 19005
author:
type: other
Loading
Loading
@@ -14,9 +14,13 @@ rackup 'config.ru'
pidfile '/home/git/gitlab/tmp/pids/puma.pid'
state_path '/home/git/gitlab/tmp/pids/puma.state'
 
stdout_redirect '/home/git/gitlab/log/puma.stdout.log',
'/home/git/gitlab/log/puma.stderr.log',
true
## Uncomment the lines if you would like to write puma stdout & stderr streams
## to a different location than rails logs.
## When using GitLab Development Kit, by default, these logs will be consumed
## by runit and can be accessed using `gdk tail rails-web`
# stdout_redirect '/home/git/gitlab/log/puma.stdout.log',
# '/home/git/gitlab/log/puma.stderr.log',
# true
 
# Configure "min" to be the minimum number of threads to use to answer
# requests and "max" the maximum.
Loading
Loading
Loading
Loading
@@ -15,6 +15,8 @@ as much as possible.
 
The current stages are:
 
- `sync`: This stage is used to synchronize changes from gitlab-org/gitlab to
gitlab-org/gitlab-foss.
- `prepare`: This stage includes jobs that prepare artifacts that are needed by
jobs in subsequent stages.
- `quick-test`: This stage includes test jobs that should run first and fail the
Loading
Loading
Loading
Loading
@@ -21,5 +21,49 @@ module Gitlab
payload[:rugged_duration_ms] = Gitlab::RuggedInstrumentation.query_time_ms
end
end
# Returns the queuing duration for a Sidekiq job in seconds, as a float, if the
# `enqueued_at` field or `created_at` field is available.
#
# * If the job doesn't contain sufficient information, returns nil
# * If the job has a start time in the future, returns 0
# * If the job contains an invalid start time value, returns nil
# @param [Hash] job a Sidekiq job, represented as a hash
def self.queue_duration_for_job(job)
# Old gitlab-shell messages don't provide enqueued_at/created_at attributes
enqueued_at = job['enqueued_at'] || job['created_at']
return unless enqueued_at
enqueued_at_time = convert_to_time(enqueued_at)
return unless enqueued_at_time
# Its possible that if theres clock-skew between two nodes
# this value may be less than zero. In that event, we record the value
# as zero.
[elapsed_by_absolute_time(enqueued_at_time), 0].max
end
# Calculates the time in seconds, as a float, from
# the provided start time until now
#
# @param [Time] start
def self.elapsed_by_absolute_time(start)
(Time.now - start).to_f.round(6)
end
private_class_method :elapsed_by_absolute_time
# Convert a representation of a time into a `Time` value
#
# @param time_value String, Float time representation, or nil
def self.convert_to_time(time_value)
return time_value if time_value.is_a?(Time)
return Time.iso8601(time_value) if time_value.is_a?(String)
return Time.at(time_value) if time_value.is_a?(Numeric) && time_value > 0
rescue ArgumentError
# Swallow invalid dates. Better to loose some observability
# than bring all background processing down because of a date
# formatting bug in a client
end
private_class_method :convert_to_time
end
end
Loading
Loading
@@ -36,11 +36,8 @@ module Gitlab
payload['message'] = "#{base_message(payload)}: start"
payload['job_status'] = 'start'
 
# Old gitlab-shell messages don't provide enqueued_at/created_at attributes
enqueued_at = payload['enqueued_at'] || payload['created_at']
if enqueued_at
payload['scheduling_latency_s'] = elapsed_by_absolute_time(Time.iso8601(enqueued_at))
end
scheduling_latency_s = ::Gitlab::InstrumentationHelper.queue_duration_for_job(payload)
payload['scheduling_latency_s'] = scheduling_latency_s if scheduling_latency_s
 
payload
end
Loading
Loading
@@ -98,10 +95,6 @@ module Gitlab
end
end
 
def elapsed_by_absolute_time(start)
(Time.now.utc - start).to_f.round(6)
end
def elapsed(t0)
t1 = get_time
{
Loading
Loading
Loading
Loading
@@ -15,6 +15,9 @@ module Gitlab
 
def call(_worker, job, queue)
labels = create_labels(queue)
queue_duration = ::Gitlab::InstrumentationHelper.queue_duration_for_job(job)
@metrics[:sidekiq_jobs_queue_duration_seconds].observe(labels, queue_duration) if queue_duration
@metrics[:sidekiq_running_jobs].increment(labels, 1)
 
if job['retry_count'].present?
Loading
Loading
@@ -49,12 +52,13 @@ module Gitlab
 
def init_metrics
{
sidekiq_jobs_cpu_seconds: ::Gitlab::Metrics.histogram(:sidekiq_jobs_cpu_seconds, 'Seconds of cpu time to run sidekiq job', {}, SIDEKIQ_LATENCY_BUCKETS),
sidekiq_jobs_completion_seconds: ::Gitlab::Metrics.histogram(:sidekiq_jobs_completion_seconds, 'Seconds to complete sidekiq job', {}, SIDEKIQ_LATENCY_BUCKETS),
sidekiq_jobs_failed_total: ::Gitlab::Metrics.counter(:sidekiq_jobs_failed_total, 'Sidekiq jobs failed'),
sidekiq_jobs_retried_total: ::Gitlab::Metrics.counter(:sidekiq_jobs_retried_total, 'Sidekiq jobs retried'),
sidekiq_running_jobs: ::Gitlab::Metrics.gauge(:sidekiq_running_jobs, 'Number of Sidekiq jobs running', {}, :all),
sidekiq_concurrency: ::Gitlab::Metrics.gauge(:sidekiq_concurrency, 'Maximum number of Sidekiq jobs', {}, :all)
sidekiq_jobs_cpu_seconds: ::Gitlab::Metrics.histogram(:sidekiq_jobs_cpu_seconds, 'Seconds of cpu time to run Sidekiq job', {}, SIDEKIQ_LATENCY_BUCKETS),
sidekiq_jobs_completion_seconds: ::Gitlab::Metrics.histogram(:sidekiq_jobs_completion_seconds, 'Seconds to complete Sidekiq job', {}, SIDEKIQ_LATENCY_BUCKETS),
sidekiq_jobs_queue_duration_seconds: ::Gitlab::Metrics.histogram(:sidekiq_jobs_queue_duration_seconds, 'Duration in seconds that a Sidekiq job was queued before being executed', {}, SIDEKIQ_LATENCY_BUCKETS),
sidekiq_jobs_failed_total: ::Gitlab::Metrics.counter(:sidekiq_jobs_failed_total, 'Sidekiq jobs failed'),
sidekiq_jobs_retried_total: ::Gitlab::Metrics.counter(:sidekiq_jobs_retried_total, 'Sidekiq jobs retried'),
sidekiq_running_jobs: ::Gitlab::Metrics.gauge(:sidekiq_running_jobs, 'Number of Sidekiq jobs running', {}, :all),
sidekiq_concurrency: ::Gitlab::Metrics.gauge(:sidekiq_concurrency, 'Maximum number of Sidekiq jobs', {}, :all)
}
end
 
Loading
Loading
Loading
Loading
@@ -8656,6 +8656,9 @@ msgstr[1] ""
msgid "Hide values"
msgstr ""
 
msgid "Hiding all labels"
msgstr ""
msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
msgstr ""
 
Loading
Loading
@@ -14813,6 +14816,9 @@ msgstr ""
msgid "Select user"
msgstr ""
 
msgid "Select your role"
msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
 
Loading
Loading
@@ -15178,6 +15184,9 @@ msgstr ""
msgid "Showing all issues"
msgstr ""
 
msgid "Showing all labels"
msgstr ""
msgid "Showing last %{size} of log -"
msgstr ""
 
Loading
Loading
Loading
Loading
@@ -66,6 +66,34 @@ describe 'User edit profile' do
end
end
 
describe 'when I change my role' do
context 'experiment enabled' do
before do
stub_experiment_for_user(signup_flow: true)
visit(profile_path)
end
it 'changes my role' do
expect(page).to have_content 'Role'
select 'Data Analyst', from: 'user_role'
submit_settings
user.reload
expect(user.role).to eq 'data_analyst'
end
end
context 'experiment disabled' do
before do
stub_experiment_for_user(signup_flow: false)
visit(profile_path)
end
it 'does not show the role picker' do
expect(page).not_to have_content 'Role'
end
end
end
context 'user avatar' do
before do
attach_file(:user_avatar, Rails.root.join('spec', 'fixtures', 'banana_sample.gif'))
Loading
Loading
import getters from '~/boards/stores/getters';
describe('Boards - Getters', () => {
describe('getLabelToggleState', () => {
it('should return "on" when isShowingLabels is true', () => {
const state = {
isShowingLabels: true,
};
expect(getters.getLabelToggleState(state)).toBe('on');
});
it('should return "off" when isShowingLabels is false', () => {
const state = {
isShowingLabels: false,
};
expect(getters.getLabelToggleState(state)).toBe('off');
});
});
});
Loading
Loading
@@ -10,6 +10,7 @@ import eventHub from '~/boards/eventhub';
import '~/boards/models/label';
import '~/boards/models/assignee';
import '~/boards/models/list';
import store from '~/boards/stores';
import boardsStore from '~/boards/stores/boards_store';
import boardCard from '~/boards/components/board_card.vue';
import { listObj, boardsMockInterceptor, mockBoardService } from './mock_data';
Loading
Loading
@@ -40,6 +41,7 @@ describe('Board card', () => {
list.issues[0].labels.push(label1);
 
vm = new BoardCardComp({
store,
propsData: {
list,
issue: list.issues[0],
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment