Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
035cd5ee5e
commit
690c904b5e
|
@ -177,7 +177,7 @@ export default class MergeRequestTabs {
|
|||
this.peek = document.getElementById('js-peek');
|
||||
this.sidebar = document.querySelector('.js-right-sidebar');
|
||||
this.pageLayout = document.querySelector('.layout-page');
|
||||
this.expandSidebar = document.querySelector('.js-expand-sidebar');
|
||||
this.expandSidebar = document.querySelectorAll('.js-expand-sidebar, .js-sidebar-toggle');
|
||||
this.paddingTop = 16;
|
||||
|
||||
this.scrollPositions = {};
|
||||
|
@ -282,7 +282,11 @@ export default class MergeRequestTabs {
|
|||
const tab = this.mergeRequestTabs.querySelector(`.${action}-tab`);
|
||||
if (tab) tab.classList.add('active');
|
||||
|
||||
this.expandSidebar?.classList.toggle('gl-display-none!', action !== 'show');
|
||||
if (window.gon?.features?.movedMrSidebar) {
|
||||
this.expandSidebar?.forEach((el) =>
|
||||
el.classList.toggle('gl-display-none!', action !== 'show'),
|
||||
);
|
||||
}
|
||||
|
||||
if (action === 'commits') {
|
||||
this.loadCommits(href);
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
import { toSafeInteger } from 'lodash';
|
||||
import csrf from '~/lib/utils/csrf';
|
||||
import { __, n__, s__, sprintf } from '~/locale';
|
||||
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import SignupCheckbox from './signup_checkbox.vue';
|
||||
|
||||
const DENYLIST_TYPE_RAW = 'raw';
|
||||
|
@ -31,7 +32,12 @@ export default {
|
|||
GlLink,
|
||||
SignupCheckbox,
|
||||
GlModal,
|
||||
PasswordComplexityCheckboxGroup: () =>
|
||||
import(
|
||||
'ee_component/pages/admin/application_settings/general/components/password_complexity_checkbox_group.vue'
|
||||
),
|
||||
},
|
||||
mixins: [glFeatureFlagMixin()],
|
||||
inject: [
|
||||
'host',
|
||||
'settingsPath',
|
||||
|
@ -178,6 +184,9 @@ export default {
|
|||
|
||||
this.submitForm();
|
||||
},
|
||||
setPasswordComplexity({ name, value }) {
|
||||
this.$set(this.form, name, value);
|
||||
},
|
||||
submitForm() {
|
||||
this.$refs.form.submit();
|
||||
},
|
||||
|
@ -291,9 +300,7 @@ export default {
|
|||
<template #description>
|
||||
<gl-sprintf
|
||||
:message="
|
||||
s__(
|
||||
'ApplicationSettings|See GitLab\'s %{linkStart}Password Policy Guidelines%{linkEnd}.',
|
||||
)
|
||||
s__('ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}.')
|
||||
"
|
||||
>
|
||||
<template #link="{ content }">
|
||||
|
@ -305,6 +312,10 @@ export default {
|
|||
</template>
|
||||
</gl-form-group>
|
||||
|
||||
<password-complexity-checkbox-group
|
||||
v-if="glFeatures.passwordComplexity"
|
||||
@set-password-complexity="setPasswordComplexity"
|
||||
/>
|
||||
<gl-form-group
|
||||
:description="$options.i18n.domainAllowListDescription"
|
||||
:label="$options.i18n.domainAllowListLabel"
|
||||
|
|
|
@ -18,6 +18,10 @@ export default function initSignupRestrictions(elementSelector = '#js-signup-for
|
|||
'domainDenylistEnabled',
|
||||
'denylistTypeRawSelected',
|
||||
'emailRestrictionsEnabled',
|
||||
'passwordNumberRequired',
|
||||
'passwordLowercaseRequired',
|
||||
'passwordUppercaseRequired',
|
||||
'passwordSymbolRequired',
|
||||
],
|
||||
});
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
class SnippetsFinder < UnionFinder
|
||||
include FinderMethods
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
include CreatedAtFilter
|
||||
|
||||
attr_reader :current_user, :params
|
||||
|
||||
|
@ -69,6 +70,7 @@ class SnippetsFinder < UnionFinder
|
|||
items = init_collection
|
||||
items = by_ids(items)
|
||||
items = items.with_optional_visibility(visibility_from_scope)
|
||||
items = by_created_at(items)
|
||||
|
||||
items.order_by(sort_param)
|
||||
end
|
||||
|
|
|
@ -18,6 +18,7 @@ class Snippet < ApplicationRecord
|
|||
include CanMoveRepositoryStorage
|
||||
include AfterCommitQueue
|
||||
extend ::Gitlab::Utils::Override
|
||||
include CreatedAtFilterable
|
||||
|
||||
MAX_FILE_COUNT = 10
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
= gitlab_ui_form_for runner, url: runner_form_url do |f|
|
||||
= form_errors(runner)
|
||||
= form_errors(runner, pajamas_alert: true)
|
||||
.form-group.row
|
||||
= label :active, _("Active"), class: 'col-form-label col-sm-2'
|
||||
.col-sm-10
|
||||
|
|
|
@ -59,7 +59,6 @@
|
|||
events:
|
||||
- users_creating_work_items
|
||||
- users_updating_work_item_title
|
||||
- users_updating_weight_estimate
|
||||
feature_flag: track_work_items_activity
|
||||
- name: xmau_project_management
|
||||
operator: OR
|
||||
|
@ -68,7 +67,6 @@
|
|||
events:
|
||||
- users_creating_work_items
|
||||
- users_updating_work_item_title
|
||||
- users_updating_weight_estimate
|
||||
feature_flag: track_work_items_activity
|
||||
- name: users_work_items
|
||||
operator: OR
|
||||
|
@ -77,5 +75,4 @@
|
|||
events:
|
||||
- users_creating_work_items
|
||||
- users_updating_work_item_title
|
||||
- users_updating_weight_estimate
|
||||
feature_flag: track_work_items_activity
|
||||
|
|
|
@ -30,7 +30,7 @@ Event streaming destinations receive **all** audit event data, which could inclu
|
|||
Users with at least the Owner role for a group can add event streaming destinations for it:
|
||||
|
||||
1. On the top bar, select **Menu > Groups** and find your group.
|
||||
1. On the left sidebar, select **Security & Compliance > Audit events**
|
||||
1. On the left sidebar, select **Security & Compliance > Audit events**.
|
||||
1. On the main area, select **Streams** tab.
|
||||
- When the destination list is empty, select **Add stream** to show the section for adding destinations.
|
||||
- When the destination list is not empty, select **{plus}** to show the section for adding destinations.
|
||||
|
@ -77,7 +77,7 @@ Users with at least the Owner role for a group can list event streaming destinat
|
|||
Users with at least the Owner role for a group can list event streaming destinations:
|
||||
|
||||
1. On the top bar, select **Menu > Groups** and find your group.
|
||||
1. On the left sidebar, select **Security & Compliance > Audit events**
|
||||
1. On the left sidebar, select **Security & Compliance > Audit events**.
|
||||
1. On the main area, select **Streams** tab.
|
||||
|
||||
### Use the API
|
||||
|
@ -116,7 +116,7 @@ When the last destination is successfully deleted, event streaming is disabled f
|
|||
Users with at least the Owner role for a group can delete event streaming destinations.
|
||||
|
||||
1. On the top bar, select **Menu > Groups** and find your group.
|
||||
1. On the left sidebar, select **Security & Compliance > Audit events**
|
||||
1. On the left sidebar, select **Security & Compliance > Audit events**.
|
||||
1. On the main area, select **Streams** tab.
|
||||
1. Select **{remove}** at the right side of each item.
|
||||
|
||||
|
@ -185,7 +185,7 @@ not available. The UI for this feature is not ready for production use.
|
|||
Users with at least the Owner role for a group can add event streaming destinations and custom HTTP headers for it:
|
||||
|
||||
1. On the top bar, select **Menu > Groups** and find your group.
|
||||
1. On the left sidebar, select **Security & Compliance > Audit events**
|
||||
1. On the left sidebar, select **Security & Compliance > Audit events**.
|
||||
1. On the main area, select **Streams** tab.
|
||||
- When the destination list is empty, select **Add stream** to show the section for adding destinations.
|
||||
- When the destination list is not empty, select **{plus}** to show the section for adding destinations.
|
||||
|
@ -221,7 +221,7 @@ mutation {
|
|||
### Deleting custom HTTP headers
|
||||
|
||||
Group owners can remove a HTTP header using the GraphQL `auditEventsStreamingHeadersDestroy` mutation. You can retrieve the header ID
|
||||
by [listing all the custom headers](#list-all-custom-headers-with-the-api) on the group.
|
||||
by [listing all the custom headers](#list-all-custom-headers) on the group.
|
||||
|
||||
```graphql
|
||||
mutation {
|
||||
|
@ -233,7 +233,11 @@ mutation {
|
|||
|
||||
The header is deleted if the returned `errors` object is empty.
|
||||
|
||||
### List all custom headers with the API
|
||||
### List all custom headers
|
||||
|
||||
List all custom HTTP headers with the API or GitLab UI.
|
||||
|
||||
#### Use the API
|
||||
|
||||
You can list all custom headers for a top-level group as well as their value and ID using the GraphQL `externalAuditEventDestinations` query. The ID
|
||||
value returned by this query is what you need to pass to the `deletion` mutation.
|
||||
|
@ -259,6 +263,22 @@ query {
|
|||
}
|
||||
```
|
||||
|
||||
#### Use the GitLab UI
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default the UI for this feature is not available. To make it available per group, ask an administrator to
|
||||
[enable the feature flag](../administration/feature_flags.md) named `custom_headers_streaming_audit_events_ui`. On GitLab.com, the UI for this feature is
|
||||
not available. The UI for this feature is not ready for production use.
|
||||
|
||||
Users with at least the Owner role for a group can add event streaming destinations and custom HTTP headers for it:
|
||||
|
||||
1. On the top bar, select **Menu > Groups** and find your group.
|
||||
1. On the left sidebar, select **Security & Compliance > Audit events**.
|
||||
1. On the main area, select **Streams** tab.
|
||||
1. Select **{pencil}** at the right side of an item.
|
||||
1. A read-only view of the items custom headers is shown. To track progress on adding editing functionality, see the [relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/361925).
|
||||
1. Select **Cancel** to close the read-only view.
|
||||
|
||||
## Verify event authenticity
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345424) in GitLab 14.8.
|
||||
|
|
|
@ -31,6 +31,15 @@ Get a list of the current user's snippets.
|
|||
GET /snippets
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
|------------------|----------|----------|-----------------------------------------------------------------------------------------------------|
|
||||
| `per_page` | integer | no | Number of snippets to return per page. |
|
||||
| `page` | integer | no | Page to retrieve. |
|
||||
| `created_after` | datetime | no | Return snippets created after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
|
||||
| `created_before` | datetime | no | Return snippets created before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
|
||||
|
||||
Example request:
|
||||
|
||||
```shell
|
||||
|
@ -389,10 +398,12 @@ GET /snippets/public
|
|||
|
||||
Parameters:
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
|:-----------|:--------|:---------|:---------------------------------------|
|
||||
| `per_page` | integer | no | Number of snippets to return per page. |
|
||||
| `page` | integer | no | Page to retrieve. |
|
||||
| Attribute | Type | Required | Description |
|
||||
|------------------|----------|----------|-----------------------------------------------------------------------------------------------------|
|
||||
| `per_page` | integer | no | Number of snippets to return per page. |
|
||||
| `page` | integer | no | Page to retrieve. |
|
||||
| `created_after` | datetime | no | Return snippets created after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
|
||||
| `created_before` | datetime | no | Return snippets created before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
|
||||
|
||||
Example request:
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ To retrieve metrics for change failure rate, use the [GraphQL](../../api/graphql
|
|||
| `lead_time_for_changes` | Project | [GitLab 13.10 and later](../../api/dora/metrics.md) | GitLab 13.11 and later | Unit in seconds. Aggregation method is median. |
|
||||
| `lead_time_for_changes` | Group | [GitLab 13.10 and later](../../api/dora/metrics.md) | GitLab 14.0 and later | Unit in seconds. Aggregation method is median. |
|
||||
| `time_to_restore_service` | Project and group | [GitLab 14.9 and later](../../api/dora/metrics.md) | GitLab 15.1 and later | Unit in days. Aggregation method is median. |
|
||||
| `change_failure_rate` | Project and group | [GitLab 14.10 and later](../../api/dora/metrics.md) | Not supported | |
|
||||
| `change_failure_rate` | Project and group | [GitLab 14.10 and later](../../api/dora/metrics.md) | GitLab 15.2 and later | Percentage of deployments. | |
|
||||
|
||||
## Definitions
|
||||
|
||||
|
|
|
@ -29,12 +29,16 @@ module API
|
|||
success Entities::Snippet
|
||||
end
|
||||
params do
|
||||
optional :created_after, type: DateTime, desc: 'Return snippets created after the specified time'
|
||||
optional :created_before, type: DateTime, desc: 'Return snippets created before the specified time'
|
||||
|
||||
use :pagination
|
||||
end
|
||||
get do
|
||||
authenticate!
|
||||
|
||||
present paginate(snippets_for_current_user), with: Entities::Snippet, current_user: current_user
|
||||
filter_params = declared_params(include_missing: false).merge(author: current_user)
|
||||
present paginate(SnippetsFinder.new(current_user, filter_params).execute), with: Entities::Snippet, current_user: current_user
|
||||
end
|
||||
|
||||
desc 'List all public personal snippets current_user has access to' do
|
||||
|
@ -42,12 +46,16 @@ module API
|
|||
success Entities::PersonalSnippet
|
||||
end
|
||||
params do
|
||||
optional :created_after, type: DateTime, desc: 'Return snippets created after the specified time'
|
||||
optional :created_before, type: DateTime, desc: 'Return snippets created before the specified time'
|
||||
|
||||
use :pagination
|
||||
end
|
||||
get 'public', urgency: :low do
|
||||
authenticate!
|
||||
|
||||
present paginate(public_snippets), with: Entities::PersonalSnippet, current_user: current_user
|
||||
filter_params = declared_params(include_missing: false).merge(only_personal: true)
|
||||
present paginate(SnippetsFinder.new(nil, filter_params).execute), with: Entities::PersonalSnippet, current_user: current_user
|
||||
end
|
||||
|
||||
desc 'Get a single snippet' do
|
||||
|
|
|
@ -145,6 +145,8 @@ module Gitlab
|
|||
sleep(CHECK_INTERVAL_SECONDS)
|
||||
|
||||
refresh_state(:above_soft_limit)
|
||||
|
||||
log_rss_out_of_range(false)
|
||||
end
|
||||
|
||||
# There are two chances to break from loop:
|
||||
|
@ -153,28 +155,49 @@ module Gitlab
|
|||
# When `above hard limit`, it immediately go to `stop_fetching_new_jobs`
|
||||
# So ignore `above hard limit` and always set `above_soft_limit` here
|
||||
refresh_state(:above_soft_limit)
|
||||
log_rss_out_of_range(@current_rss, @hard_limit_rss, @soft_limit_rss)
|
||||
log_rss_out_of_range
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
def log_rss_out_of_range(current_rss, hard_limit_rss, soft_limit_rss)
|
||||
def log_rss_out_of_range(deadline_exceeded = true)
|
||||
reason = out_of_range_description(@current_rss,
|
||||
@hard_limit_rss,
|
||||
@soft_limit_rss,
|
||||
deadline_exceeded)
|
||||
|
||||
Sidekiq.logger.warn(
|
||||
class: self.class.to_s,
|
||||
pid: pid,
|
||||
message: 'Sidekiq worker RSS out of range',
|
||||
current_rss: current_rss,
|
||||
hard_limit_rss: hard_limit_rss,
|
||||
soft_limit_rss: soft_limit_rss,
|
||||
reason: out_of_range_description(current_rss, hard_limit_rss, soft_limit_rss)
|
||||
)
|
||||
current_rss: @current_rss,
|
||||
soft_limit_rss: @soft_limit_rss,
|
||||
hard_limit_rss: @hard_limit_rss,
|
||||
reason: reason,
|
||||
running_jobs: running_jobs)
|
||||
end
|
||||
|
||||
def out_of_range_description(rss, hard_limit, soft_limit)
|
||||
def running_jobs
|
||||
jobs = []
|
||||
Gitlab::SidekiqDaemon::Monitor.instance.jobs_mutex.synchronize do
|
||||
jobs = Gitlab::SidekiqDaemon::Monitor.instance.jobs.map do |jid, job|
|
||||
{
|
||||
jid: jid,
|
||||
worker_class: job[:worker_class].name
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
jobs
|
||||
end
|
||||
|
||||
def out_of_range_description(rss, hard_limit, soft_limit, deadline_exceeded)
|
||||
if rss > hard_limit
|
||||
"current_rss(#{rss}) > hard_limit_rss(#{hard_limit})"
|
||||
else
|
||||
elsif deadline_exceeded
|
||||
"current_rss(#{rss}) > soft_limit_rss(#{soft_limit}) longer than GRACE_BALLOON_SECONDS(#{GRACE_BALLOON_SECONDS})"
|
||||
else
|
||||
"current_rss(#{rss}) > soft_limit_rss(#{soft_limit})"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -757,6 +757,9 @@ msgstr ""
|
|||
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
|
||||
msgstr ""
|
||||
|
||||
msgid "%{labelStart}URL:%{labelEnd} %{url}"
|
||||
msgstr ""
|
||||
|
||||
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
|
||||
msgstr ""
|
||||
|
||||
|
@ -4592,13 +4595,25 @@ msgstr ""
|
|||
msgid "ApplicationSettings|Require admin approval for new sign-ups"
|
||||
msgstr ""
|
||||
|
||||
msgid "ApplicationSettings|Require lowercase letters"
|
||||
msgstr ""
|
||||
|
||||
msgid "ApplicationSettings|Require numbers"
|
||||
msgstr ""
|
||||
|
||||
msgid "ApplicationSettings|Require symbols"
|
||||
msgstr ""
|
||||
|
||||
msgid "ApplicationSettings|Require uppercase letters"
|
||||
msgstr ""
|
||||
|
||||
msgid "ApplicationSettings|Restricts sign-ups for email addresses that match the given regex. %{linkStart}What is the supported syntax?%{linkEnd}"
|
||||
msgstr ""
|
||||
|
||||
msgid "ApplicationSettings|Save changes"
|
||||
msgstr ""
|
||||
|
||||
msgid "ApplicationSettings|See GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
|
||||
msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "ApplicationSettings|Send confirmation email on sign-up"
|
||||
|
@ -4625,6 +4640,18 @@ msgstr ""
|
|||
msgid "ApplicationSettings|Users with e-mail addresses that match these domain(s) cannot sign up. Wildcards allowed. Use separate lines or commas for multiple entries."
|
||||
msgstr ""
|
||||
|
||||
msgid "ApplicationSettings|When enabled, new passwords must contain at least one lowercase letter (a-z)."
|
||||
msgstr ""
|
||||
|
||||
msgid "ApplicationSettings|When enabled, new passwords must contain at least one number (0-9)."
|
||||
msgstr ""
|
||||
|
||||
msgid "ApplicationSettings|When enabled, new passwords must contain at least one symbol."
|
||||
msgstr ""
|
||||
|
||||
msgid "ApplicationSettings|When enabled, new passwords must contain at least one uppercase letter (A-Z)."
|
||||
msgstr ""
|
||||
|
||||
msgid "ApplicationSettings|domain.com"
|
||||
msgstr ""
|
||||
|
||||
|
@ -5337,12 +5364,18 @@ msgstr ""
|
|||
msgid "AuditStreams|Destinations receive all audit event data"
|
||||
msgstr ""
|
||||
|
||||
msgid "AuditStreams|Edit %{link}"
|
||||
msgstr ""
|
||||
|
||||
msgid "AuditStreams|Header"
|
||||
msgstr ""
|
||||
|
||||
msgid "AuditStreams|Maximum of %{number} HTTP headers has been reached."
|
||||
msgstr ""
|
||||
|
||||
msgid "AuditStreams|Save external stream destination"
|
||||
msgstr ""
|
||||
|
||||
msgid "AuditStreams|Setup streaming for audit events"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -18,6 +18,10 @@ export const rawMockData = {
|
|||
emailRestrictions: 'user1@domain.com, user2@domain.com',
|
||||
afterSignUpText: 'Congratulations on your successful sign-up!',
|
||||
pendingUserCount: '0',
|
||||
passwordNumberRequired: 'true',
|
||||
passwordLowercaseRequired: 'true',
|
||||
passwordUppercaseRequired: 'true',
|
||||
passwordSymbolRequired: 'true',
|
||||
};
|
||||
|
||||
export const mockData = {
|
||||
|
@ -40,4 +44,8 @@ export const mockData = {
|
|||
emailRestrictions: 'user1@domain.com, user2@domain.com',
|
||||
afterSignUpText: 'Congratulations on your successful sign-up!',
|
||||
pendingUserCount: '0',
|
||||
passwordNumberRequired: true,
|
||||
passwordLowercaseRequired: true,
|
||||
passwordUppercaseRequired: true,
|
||||
passwordSymbolRequired: true,
|
||||
};
|
||||
|
|
|
@ -14,6 +14,10 @@ describe('utils', () => {
|
|||
'domainDenylistEnabled',
|
||||
'denylistTypeRawSelected',
|
||||
'emailRestrictionsEnabled',
|
||||
'passwordNumberRequired',
|
||||
'passwordLowercaseRequired',
|
||||
'passwordUppercaseRequired',
|
||||
'passwordSymbolRequired',
|
||||
],
|
||||
}),
|
||||
).toEqual(mockData);
|
||||
|
|
|
@ -334,6 +334,8 @@ describe('MergeRequestTabs', () => {
|
|||
${'diffs'} | ${true} | ${'hides'}
|
||||
${'commits'} | ${true} | ${'hides'}
|
||||
`('it $hidesText expand button on $tab tab', ({ tab, hides }) => {
|
||||
window.gon = { features: { movedMrSidebar: true } };
|
||||
|
||||
const expandButton = document.createElement('div');
|
||||
expandButton.classList.add('js-expand-sidebar');
|
||||
|
||||
|
@ -347,7 +349,11 @@ describe('MergeRequestTabs', () => {
|
|||
testContext.class = new MergeRequestTabs({ stubLocation });
|
||||
testContext.class.tabShown(tab, 'foobar');
|
||||
|
||||
expect(testContext.class.expandSidebar.classList.contains('gl-display-none!')).toBe(hides);
|
||||
testContext.class.expandSidebar.forEach((el) => {
|
||||
expect(el.classList.contains('gl-display-none!')).toBe(hides);
|
||||
});
|
||||
|
||||
window.gon = {};
|
||||
});
|
||||
|
||||
describe('when switching tabs', () => {
|
||||
|
|
|
@ -129,7 +129,7 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
|||
allow(Sidekiq).to receive(:options).and_return(timeout: 9)
|
||||
end
|
||||
|
||||
it 'return true when everything is within limit' do
|
||||
it 'return true when everything is within limit', :aggregate_failures do
|
||||
expect(memory_killer).to receive(:get_rss).and_return(100)
|
||||
expect(memory_killer).to receive(:get_soft_limit_rss).and_return(200)
|
||||
expect(memory_killer).to receive(:get_hard_limit_rss).and_return(300)
|
||||
|
@ -144,7 +144,7 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
|||
expect(subject).to be true
|
||||
end
|
||||
|
||||
it 'return false when rss exceeds hard_limit_rss' do
|
||||
it 'return false when rss exceeds hard_limit_rss', :aggregate_failures do
|
||||
expect(memory_killer).to receive(:get_rss).at_least(:once).and_return(400)
|
||||
expect(memory_killer).to receive(:get_soft_limit_rss).at_least(:once).and_return(200)
|
||||
expect(memory_killer).to receive(:get_hard_limit_rss).at_least(:once).and_return(300)
|
||||
|
@ -159,12 +159,12 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
|||
|
||||
expect(Gitlab::Metrics::System).to receive(:monotonic_time).and_call_original
|
||||
|
||||
expect(memory_killer).to receive(:log_rss_out_of_range).with(400, 300, 200)
|
||||
expect(memory_killer).to receive(:out_of_range_description).with(400, 300, 200, true)
|
||||
|
||||
expect(subject).to be false
|
||||
end
|
||||
|
||||
it 'return false when rss exceed hard_limit_rss after a while' do
|
||||
it 'return false when rss exceed hard_limit_rss after a while', :aggregate_failures do
|
||||
expect(memory_killer).to receive(:get_rss).and_return(250, 400, 400)
|
||||
expect(memory_killer).to receive(:get_soft_limit_rss).at_least(:once).and_return(200)
|
||||
expect(memory_killer).to receive(:get_hard_limit_rss).at_least(:once).and_return(300)
|
||||
|
@ -180,12 +180,13 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
|||
|
||||
expect(Gitlab::Metrics::System).to receive(:monotonic_time).twice.and_call_original
|
||||
expect(memory_killer).to receive(:sleep).with(check_interval_seconds)
|
||||
expect(memory_killer).to receive(:log_rss_out_of_range).with(400, 300, 200)
|
||||
expect(memory_killer).to receive(:out_of_range_description).with(400, 300, 200, false)
|
||||
expect(memory_killer).to receive(:out_of_range_description).with(400, 300, 200, true)
|
||||
|
||||
expect(subject).to be false
|
||||
end
|
||||
|
||||
it 'return true when rss below soft_limit_rss after a while within GRACE_BALLOON_SECONDS' do
|
||||
it 'return true when rss below soft_limit_rss after a while within GRACE_BALLOON_SECONDS', :aggregate_failures do
|
||||
expect(memory_killer).to receive(:get_rss).and_return(250, 100)
|
||||
expect(memory_killer).to receive(:get_soft_limit_rss).and_return(200, 200)
|
||||
expect(memory_killer).to receive(:get_hard_limit_rss).and_return(300, 300)
|
||||
|
@ -201,15 +202,15 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
|||
expect(Gitlab::Metrics::System).to receive(:monotonic_time).twice.and_call_original
|
||||
expect(memory_killer).to receive(:sleep).with(check_interval_seconds)
|
||||
|
||||
expect(memory_killer).not_to receive(:log_rss_out_of_range)
|
||||
expect(memory_killer).to receive(:out_of_range_description).with(100, 300, 200, false)
|
||||
|
||||
expect(subject).to be true
|
||||
end
|
||||
|
||||
context 'when exceeding GRACE_BALLOON_SECONDS' do
|
||||
context 'when exceeds GRACE_BALLOON_SECONDS' do
|
||||
let(:grace_balloon_seconds) { 0 }
|
||||
|
||||
it 'return false when rss exceed soft_limit_rss' do
|
||||
it 'return false when rss exceed soft_limit_rss', :aggregate_failures do
|
||||
allow(memory_killer).to receive(:get_rss).and_return(250)
|
||||
allow(memory_killer).to receive(:get_soft_limit_rss).and_return(200)
|
||||
allow(memory_killer).to receive(:get_hard_limit_rss).and_return(300)
|
||||
|
@ -222,8 +223,7 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
|||
.with(:above_soft_limit)
|
||||
.and_call_original
|
||||
|
||||
expect(memory_killer).to receive(:log_rss_out_of_range)
|
||||
.with(250, 300, 200)
|
||||
expect(memory_killer).to receive(:out_of_range_description).with(250, 300, 200, true)
|
||||
|
||||
expect(subject).to be false
|
||||
end
|
||||
|
@ -318,7 +318,7 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
|||
|
||||
subject { memory_killer.send(:signal_pgroup, signal, explanation) }
|
||||
|
||||
it 'send signal to this proces if it is not group leader' do
|
||||
it 'send signal to this process if it is not group leader' do
|
||||
expect(Process).to receive(:getpgrp).and_return(pid + 1)
|
||||
|
||||
expect(Sidekiq.logger).to receive(:warn).once
|
||||
|
@ -351,12 +351,34 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
|||
let(:current_rss) { 100 }
|
||||
let(:soft_limit_rss) { 200 }
|
||||
let(:hard_limit_rss) { 300 }
|
||||
let(:jid) { 1 }
|
||||
let(:reason) { 'rss out of range reason description' }
|
||||
let(:queue) { 'default' }
|
||||
let(:running_jobs) { [{ jid: jid, worker_class: 'DummyWorker' }] }
|
||||
let(:worker) do
|
||||
Class.new do
|
||||
def self.name
|
||||
'DummyWorker'
|
||||
end
|
||||
|
||||
subject { memory_killer.send(:log_rss_out_of_range, current_rss, hard_limit_rss, soft_limit_rss) }
|
||||
include ApplicationWorker
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
stub_const("DummyWorker", worker)
|
||||
|
||||
allow(memory_killer).to receive(:get_rss).and_return(*current_rss)
|
||||
allow(memory_killer).to receive(:get_soft_limit_rss).and_return(soft_limit_rss)
|
||||
allow(memory_killer).to receive(:get_hard_limit_rss).and_return(hard_limit_rss)
|
||||
|
||||
memory_killer.send(:refresh_state, :running)
|
||||
end
|
||||
|
||||
subject { memory_killer.send(:log_rss_out_of_range) }
|
||||
|
||||
it 'invoke sidekiq logger warn' do
|
||||
expect(memory_killer).to receive(:out_of_range_description).with(current_rss, hard_limit_rss, soft_limit_rss).and_return(reason)
|
||||
expect(memory_killer).to receive(:out_of_range_description).with(current_rss, hard_limit_rss, soft_limit_rss, true).and_return(reason)
|
||||
expect(Sidekiq.logger).to receive(:warn)
|
||||
.with(
|
||||
class: described_class.to_s,
|
||||
|
@ -365,9 +387,12 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
|||
current_rss: current_rss,
|
||||
hard_limit_rss: hard_limit_rss,
|
||||
soft_limit_rss: soft_limit_rss,
|
||||
reason: reason)
|
||||
reason: reason,
|
||||
running_jobs: running_jobs)
|
||||
|
||||
subject
|
||||
Gitlab::SidekiqDaemon::Monitor.instance.within_job(DummyWorker, jid, queue) do
|
||||
subject
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -375,8 +400,9 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
|||
let(:hard_limit) { 300 }
|
||||
let(:soft_limit) { 200 }
|
||||
let(:grace_balloon_seconds) { 12 }
|
||||
let(:deadline_exceeded) { true }
|
||||
|
||||
subject { memory_killer.send(:out_of_range_description, rss, hard_limit, soft_limit) }
|
||||
subject { memory_killer.send(:out_of_range_description, rss, hard_limit, soft_limit, deadline_exceeded) }
|
||||
|
||||
context 'when rss > hard_limit' do
|
||||
let(:rss) { 400 }
|
||||
|
@ -389,9 +415,20 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
|||
context 'when rss <= hard_limit' do
|
||||
let(:rss) { 300 }
|
||||
|
||||
it 'tells reason' do
|
||||
stub_const("#{described_class}::GRACE_BALLOON_SECONDS", grace_balloon_seconds)
|
||||
expect(subject).to eq("current_rss(#{rss}) > soft_limit_rss(#{soft_limit}) longer than GRACE_BALLOON_SECONDS(#{grace_balloon_seconds})")
|
||||
context 'deadline exceeded' do
|
||||
let(:deadline_exceeded) { true }
|
||||
|
||||
it 'tells reason' do
|
||||
stub_const("#{described_class}::GRACE_BALLOON_SECONDS", grace_balloon_seconds)
|
||||
expect(subject).to eq("current_rss(#{rss}) > soft_limit_rss(#{soft_limit}) longer than GRACE_BALLOON_SECONDS(#{grace_balloon_seconds})")
|
||||
end
|
||||
end
|
||||
context 'deadline not exceeded' do
|
||||
let(:deadline_exceeded) { false }
|
||||
|
||||
it 'tells reason' do
|
||||
expect(subject).to eq("current_rss(#{rss}) > soft_limit_rss(#{soft_limit})")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,9 +9,9 @@ RSpec.describe API::Snippets, factory_default: :keep do
|
|||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:other_user) { create(:user) }
|
||||
|
||||
let_it_be(:public_snippet) { create(:personal_snippet, :repository, :public, author: user) }
|
||||
let_it_be(:private_snippet) { create(:personal_snippet, :repository, :private, author: user) }
|
||||
let_it_be(:internal_snippet) { create(:personal_snippet, :repository, :internal, author: user) }
|
||||
let_it_be(:public_snippet) { create(:personal_snippet, :repository, :public, author: user) }
|
||||
let_it_be_with_refind(:private_snippet) { create(:personal_snippet, :repository, :private, author: user) }
|
||||
let_it_be(:internal_snippet) { create(:personal_snippet, :repository, :internal, author: user) }
|
||||
|
||||
let_it_be(:user_token) { create(:personal_access_token, user: user) }
|
||||
let_it_be(:other_user_token) { create(:personal_access_token, user: other_user) }
|
||||
|
@ -63,6 +63,23 @@ RSpec.describe API::Snippets, factory_default: :keep do
|
|||
expect(snippet["id"]).not_to eq(public_snippet.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'filtering snippets by created_after/created_before' do
|
||||
let_it_be(:private_snippet_before_time_range) { create(:personal_snippet, :repository, :private, author: user, created_at: Time.parse("2021-08-20T00:00:00Z")) }
|
||||
let_it_be(:private_snippet_in_time_range1) { create(:personal_snippet, :repository, :private, author: user, created_at: Time.parse("2021-08-22T00:00:00Z")) }
|
||||
let_it_be(:private_snippet_in_time_range2) { create(:personal_snippet, :repository, :private, author: user, created_at: Time.parse("2021-08-24T00:00:00Z")) }
|
||||
let_it_be(:private_snippet_after_time_range) { create(:personal_snippet, :repository, :private, author: user, created_at: Time.parse("2021-08-26T00:00:00Z")) }
|
||||
|
||||
let(:path) { "/snippets?created_after=2021-08-21T00:00:00Z&created_before=2021-08-25T00:00:00Z" }
|
||||
|
||||
it 'returns snippets available for user in given time range' do
|
||||
get api(path, personal_access_token: user_token)
|
||||
|
||||
expect(json_response.map { |snippet| snippet['id']} ).to contain_exactly(
|
||||
private_snippet_in_time_range1.id,
|
||||
private_snippet_in_time_range2.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /snippets/public' do
|
||||
|
@ -98,6 +115,21 @@ RSpec.describe API::Snippets, factory_default: :keep do
|
|||
|
||||
expect(response).to have_gitlab_http_status(:unauthorized)
|
||||
end
|
||||
|
||||
context 'filtering public snippets by created_after/created_before' do
|
||||
let_it_be(:public_snippet_before_time_range) { create(:personal_snippet, :repository, :public, author: other_user, created_at: Time.parse("2021-08-20T00:00:00Z")) }
|
||||
let_it_be(:public_snippet_in_time_range) { create(:personal_snippet, :repository, :public, author: other_user, created_at: Time.parse("2021-08-22T00:00:00Z")) }
|
||||
let_it_be(:public_snippet_after_time_range) { create(:personal_snippet, :repository, :public, author: other_user, created_at: Time.parse("2021-08-24T00:00:00Z")) }
|
||||
|
||||
let(:path) { "/snippets/public?created_after=2021-08-21T00:00:00Z&created_before=2021-08-23T00:00:00Z" }
|
||||
|
||||
it 'returns public snippets available to user in given time range' do
|
||||
get api(path, personal_access_token: user_token)
|
||||
|
||||
expect(json_response.map { |snippet| snippet['id']} ).to contain_exactly(
|
||||
public_snippet_in_time_range.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /snippets/:id/raw' do
|
||||
|
|
Loading…
Reference in New Issue