diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-07-19 12:10:09 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-07-19 12:10:09 +0000 |
commit | 690c904b5e340f14c04f93ff688b647b46f7d1a2 (patch) | |
tree | 1eeb0005de86a16132fc08608494a67d5b9f4f71 | |
parent | 035cd5ee5e42fda4a896ed43147ebf455fa2f5ba (diff) | |
download | gitlab-ce-690c904b5e340f14c04f93ff688b647b46f7d1a2.tar.gz |
Add latest changes from gitlab-org/gitlab@master
-rw-r--r-- | app/assets/javascripts/merge_request_tabs.js | 8 | ||||
-rw-r--r-- | app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue | 17 | ||||
-rw-r--r-- | app/assets/javascripts/pages/admin/application_settings/signup_restrictions.js | 4 | ||||
-rw-r--r-- | app/finders/snippets_finder.rb | 2 | ||||
-rw-r--r-- | app/models/snippet.rb | 1 | ||||
-rw-r--r-- | app/views/shared/runners/_form.html.haml | 2 | ||||
-rw-r--r-- | config/metrics/aggregates/common.yml | 3 | ||||
-rw-r--r-- | doc/administration/audit_event_streaming.md | 32 | ||||
-rw-r--r-- | doc/api/snippets.md | 19 | ||||
-rw-r--r-- | doc/user/analytics/index.md | 2 | ||||
-rw-r--r-- | lib/api/snippets.rb | 12 | ||||
-rw-r--r-- | lib/gitlab/sidekiq_daemon/memory_killer.rb | 41 | ||||
-rw-r--r-- | locale/gitlab.pot | 35 | ||||
-rw-r--r-- | spec/frontend/admin/signup_restrictions/mock_data.js | 8 | ||||
-rw-r--r-- | spec/frontend/admin/signup_restrictions/utils_spec.js | 4 | ||||
-rw-r--r-- | spec/frontend/merge_request_tabs_spec.js | 8 | ||||
-rw-r--r-- | spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb | 77 | ||||
-rw-r--r-- | spec/requests/api/snippets_spec.rb | 38 |
18 files changed, 257 insertions, 56 deletions
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js index 94041d77bb0..ed2e6a5af58 100644 --- a/app/assets/javascripts/merge_request_tabs.js +++ b/app/assets/javascripts/merge_request_tabs.js @@ -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); diff --git a/app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue b/app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue index 5ecacb84d65..ccb449f96e1 100644 --- a/app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue +++ b/app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue @@ -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" diff --git a/app/assets/javascripts/pages/admin/application_settings/signup_restrictions.js b/app/assets/javascripts/pages/admin/application_settings/signup_restrictions.js index a50d8de0e88..0d5c55cb87b 100644 --- a/app/assets/javascripts/pages/admin/application_settings/signup_restrictions.js +++ b/app/assets/javascripts/pages/admin/application_settings/signup_restrictions.js @@ -18,6 +18,10 @@ export default function initSignupRestrictions(elementSelector = '#js-signup-for 'domainDenylistEnabled', 'denylistTypeRawSelected', 'emailRestrictionsEnabled', + 'passwordNumberRequired', + 'passwordLowercaseRequired', + 'passwordUppercaseRequired', + 'passwordSymbolRequired', ], }); diff --git a/app/finders/snippets_finder.rb b/app/finders/snippets_finder.rb index b1e12721712..bf20a2c2c3d 100644 --- a/app/finders/snippets_finder.rb +++ b/app/finders/snippets_finder.rb @@ -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 diff --git a/app/models/snippet.rb b/app/models/snippet.rb index cf4b83d44c2..c813c5cb5b8 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -18,6 +18,7 @@ class Snippet < ApplicationRecord include CanMoveRepositoryStorage include AfterCommitQueue extend ::Gitlab::Utils::Override + include CreatedAtFilterable MAX_FILE_COUNT = 10 diff --git a/app/views/shared/runners/_form.html.haml b/app/views/shared/runners/_form.html.haml index 024b06fe97a..e0079a95cec 100644 --- a/app/views/shared/runners/_form.html.haml +++ b/app/views/shared/runners/_form.html.haml @@ -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 diff --git a/config/metrics/aggregates/common.yml b/config/metrics/aggregates/common.yml index a6585ddec23..6396187a26a 100644 --- a/config/metrics/aggregates/common.yml +++ b/config/metrics/aggregates/common.yml @@ -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 diff --git a/doc/administration/audit_event_streaming.md b/doc/administration/audit_event_streaming.md index 019032c8b98..817f22debbc 100644 --- a/doc/administration/audit_event_streaming.md +++ b/doc/administration/audit_event_streaming.md @@ -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. diff --git a/doc/api/snippets.md b/doc/api/snippets.md index 52bcd072de9..e3bc3573ed7 100644 --- a/doc/api/snippets.md +++ b/doc/api/snippets.md @@ -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: diff --git a/doc/user/analytics/index.md b/doc/user/analytics/index.md index b8c0e9af745..f699fa6d0fb 100644 --- a/doc/user/analytics/index.md +++ b/doc/user/analytics/index.md @@ -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 diff --git a/lib/api/snippets.rb b/lib/api/snippets.rb index 496532a15b2..4e70ebddf94 100644 --- a/lib/api/snippets.rb +++ b/lib/api/snippets.rb @@ -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 diff --git a/lib/gitlab/sidekiq_daemon/memory_killer.rb b/lib/gitlab/sidekiq_daemon/memory_killer.rb index 113076a6a75..cb7d9c6f8a7 100644 --- a/lib/gitlab/sidekiq_daemon/memory_killer.rb +++ b/lib/gitlab/sidekiq_daemon/memory_killer.rb @@ -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 diff --git a/locale/gitlab.pot b/locale/gitlab.pot index b5422614ca9..e2aaf645b0a 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -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 "" diff --git a/spec/frontend/admin/signup_restrictions/mock_data.js b/spec/frontend/admin/signup_restrictions/mock_data.js index 135fc8caae0..9e001e122a4 100644 --- a/spec/frontend/admin/signup_restrictions/mock_data.js +++ b/spec/frontend/admin/signup_restrictions/mock_data.js @@ -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, }; diff --git a/spec/frontend/admin/signup_restrictions/utils_spec.js b/spec/frontend/admin/signup_restrictions/utils_spec.js index fd5c4c3317b..f07e14430f9 100644 --- a/spec/frontend/admin/signup_restrictions/utils_spec.js +++ b/spec/frontend/admin/signup_restrictions/utils_spec.js @@ -14,6 +14,10 @@ describe('utils', () => { 'domainDenylistEnabled', 'denylistTypeRawSelected', 'emailRestrictionsEnabled', + 'passwordNumberRequired', + 'passwordLowercaseRequired', + 'passwordUppercaseRequired', + 'passwordSymbolRequired', ], }), ).toEqual(mockData); diff --git a/spec/frontend/merge_request_tabs_spec.js b/spec/frontend/merge_request_tabs_spec.js index 96ac655381b..2001bb5f95e 100644 --- a/spec/frontend/merge_request_tabs_spec.js +++ b/spec/frontend/merge_request_tabs_spec.js @@ -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', () => { diff --git a/spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb b/spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb index 4a952a2040a..01b7270d761 100644 --- a/spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb +++ b/spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb @@ -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 + + 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, current_rss, hard_limit_rss, soft_limit_rss) } + 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 diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb index 13160519996..0ba1011684a 100644 --- a/spec/requests/api/snippets_spec.rb +++ b/spec/requests/api/snippets_spec.rb @@ -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 |