summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md37
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js2
-rw-r--r--app/assets/javascripts/group_settings/components/shared_runners_form.vue7
-rw-r--r--app/assets/javascripts/group_settings/constants.js3
-rw-r--r--app/assets/javascripts/group_settings/stale_runner_cleanup.js3
-rw-r--r--app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js2
-rw-r--r--app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue11
-rw-r--r--app/controllers/groups/application_controller.rb6
-rw-r--r--app/controllers/groups/group_members_controller.rb1
-rw-r--r--app/policies/ci/build_policy.rb2
-rw-r--r--app/policies/group_policy.rb9
-rw-r--r--app/policies/project_policy.rb4
-rw-r--r--app/services/ci/pipeline_trigger_service.rb1
-rw-r--r--app/services/members/import_project_team_service.rb2
-rw-r--r--app/views/groups/runners/_settings.html.haml5
-rw-r--r--config/feature_flags/development/stale_runner_cleanup_for_namespace_development.yml8
-rw-r--r--doc/administration/package_information/postgresql_versions.md3
-rw-r--r--doc/api/scim.md14
-rw-r--r--doc/ci/runners/configure_runners.md44
-rw-r--r--doc/development/code_review.md2
-rw-r--r--doc/update/index.md6
-rw-r--r--doc/user/group/subgroups/index.md3
-rw-r--r--lib/api/helpers/members_helpers.rb4
-rw-r--r--lib/api/members.rb8
-rw-r--r--lib/sidebars/projects/menus/monitor_menu.rb16
-rw-r--r--locale/gitlab.pot23
-rw-r--r--package.json2
-rw-r--r--qa/qa/page/project/settings/ci_variables.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/testing/endpoint_coverage_spec.rb92
-rw-r--r--spec/controllers/projects/jobs_controller_spec.rb8
-rw-r--r--spec/features/security/group/private_access_spec.rb2
-rw-r--r--spec/frontend/gfm_auto_complete_spec.js15
-rw-r--r--spec/frontend/runner/components/__snapshots__/runner_status_popover_spec.js.snap2
-rw-r--r--spec/frontend/runner/mock_data.js2
-rw-r--r--spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js9
-rw-r--r--spec/helpers/emails_helper_spec.rb10
-rw-r--r--spec/lib/sidebars/projects/menus/monitor_menu_spec.rb14
-rw-r--r--spec/policies/ci/build_policy_spec.rb48
-rw-r--r--spec/policies/project_policy_spec.rb30
-rw-r--r--spec/requests/api/members_spec.rb15
-rw-r--r--spec/services/ci/pipeline_trigger_service_spec.rb9
-rw-r--r--spec/support/helpers/emails_helper_test_helper.rb9
-rw-r--r--spec/support/shared_contexts/navbar_structure_context.rb1
-rw-r--r--spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb26
-rw-r--r--yarn.lock30
45 files changed, 488 insertions, 64 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8ff9327f1bf..ed401b55537 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,19 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 15.0.1 (2022-06-01)
+
+### Security (8 changes)
+
+- [Fix IP restrictions not applying to deploy tokens](gitlab-org/security/gitlab@3af76bc31e2d141e2262d65eb08fcab7f34844bf) ([merge request](gitlab-org/security/gitlab!2474))
+- [Trigger token should respect group IP restrictions](gitlab-org/security/gitlab@f9ba81383a97b014be3085524def6f01120d9e3e) ([merge request](gitlab-org/security/gitlab!2476))
+- [Fix content injection in Jira issue title](gitlab-org/security/gitlab@d0c449079ce8d680f3390e21ed08aced1bfaf17b) ([merge request](gitlab-org/security/gitlab!2463))
+- [Escape contact details correctly in quick actions](gitlab-org/security/gitlab@cbafec91630b1309354784040c572ba1f844f794) ([merge request](gitlab-org/security/gitlab!2459))
+- [Subgroup member can list members of parent group](gitlab-org/security/gitlab@93583b7fe97f59f746f719742230eadbfbdf5ce3) ([merge request](gitlab-org/security/gitlab!2479))
+- [Do not allow project member import when membership is locked](gitlab-org/security/gitlab@b6ca02c9bac46ebcc822bbeee9e75aaf184d9996) ([merge request](gitlab-org/security/gitlab!2457))
+- [Disable changing user attributes when updating SCIM provisioned user](gitlab-org/security/gitlab@660a0021e3df45893c1f4317d3aa86dd276c6071) ([merge request](gitlab-org/security/gitlab!2453))
+- [Allow only job owner to run interactive terminal](gitlab-org/security/gitlab@917c3e4e314b02da33d8b9aea07179bc74833053) ([merge request](gitlab-org/security/gitlab!2451))
+
## 15.0.0 (2022-05-20)
### Added (147 changes)
@@ -733,6 +746,18 @@ entry.
- [Move methods to build email unsubscribe link to helper](gitlab-org/gitlab@ae4391a84d14d51ca5b5f2ffaada96e3b37a1d51) ([merge request](gitlab-org/gitlab!84696)) **GitLab Enterprise Edition**
- [Deprecate `push_rules_supersede_code_owners` feature flag](gitlab-org/gitlab@9ee99872b66a69c5a2d1c1c9863d960832a1d91f) ([merge request](gitlab-org/gitlab!85390))
+## 14.10.4 (2022-06-01)
+
+### Security (7 changes)
+
+- [Fix IP restrictions not applying to deploy tokens](gitlab-org/security/gitlab@8866d00e50f1d2857d54130239851f21404d7432) ([merge request](gitlab-org/security/gitlab!2471))
+- [Trigger token should respect group IP restrictions](gitlab-org/security/gitlab@8534ca1be10f115dad2e0c1a4e167673049e401a) ([merge request](gitlab-org/security/gitlab!2478))
+- [Fix content injection in Jira issue title](gitlab-org/security/gitlab@b8f82ec8d7ddf30c656642bff12de8fc8b5930a2) ([merge request](gitlab-org/security/gitlab!2464))
+- [Subgroup member can list members of parent group](gitlab-org/security/gitlab@b59c49fa7b681a93bbe4bc69b20e72930a8b9d8d) ([merge request](gitlab-org/security/gitlab!2480))
+- [Do not allow project member import when membership is locked](gitlab-org/security/gitlab@baed30570206b5ed9973ad8bfac5462721745a5d) ([merge request](gitlab-org/security/gitlab!2447))
+- [Disable changing user attributes when updating SCIM provisioned user](gitlab-org/security/gitlab@ae4eb58668513f38c0daf1dc3b977c6b22a9a476) ([merge request](gitlab-org/security/gitlab!2454))
+- [Allow only job owner to run interactive terminal](gitlab-org/security/gitlab@b0819e77b5a65d4412b42f27a513c02cc056a2b8) ([merge request](gitlab-org/security/gitlab!2433))
+
## 14.10.3 (2022-05-20)
### Added (1 change)
@@ -1444,6 +1469,18 @@ entry.
- [Convert ci_builds-runner_id FK to LFK](gitlab-org/gitlab@5e114952616994acb802e5ded373fc07e53a3aaa) ([merge request](gitlab-org/gitlab!83129))
- [Fix related epic links and issue links specs fixtures](gitlab-org/gitlab@ffc7df0cdbdda91fec15d2c4437e64dd7d073d50) ([merge request](gitlab-org/gitlab!82623))
+## 14.9.5 (2022-06-01)
+
+### Security (7 changes)
+
+- [Fix IP restrictions not applying to deploy tokens](gitlab-org/security/gitlab@b429997e253110ea5eb4d20a8b90e9879be97300) ([merge request](gitlab-org/security/gitlab!2472))
+- [Trigger token should respect group IP restrictions](gitlab-org/security/gitlab@326993794bba8659208cde212433a5a19fd3e5a9) ([merge request](gitlab-org/security/gitlab!2477))
+- [Fix content injection in Jira issue title](gitlab-org/security/gitlab@c968f7be35d829bfefbf089794343d2d20cdd078) ([merge request](gitlab-org/security/gitlab!2465))
+- [Subgroup member can list members of parent group](gitlab-org/security/gitlab@1606689819eeae574bd5d65c8c971c2d4eb19e41) ([merge request](gitlab-org/security/gitlab!2481))
+- [Do not allow project member import when membership is locked](gitlab-org/security/gitlab@e8324068c61c4c58d50646d4fa8dff77c4d147ae) ([merge request](gitlab-org/security/gitlab!2448))
+- [Disable changing user attributes when updating SCIM provisioned user](gitlab-org/security/gitlab@9d5aca002edb2e0ab3c7d5b6eb00ea781d3dde9f) ([merge request](gitlab-org/security/gitlab!2455))
+- [Allow only job owner to run interactive terminal](gitlab-org/security/gitlab@c9fe31e3a963c421db3d9c47c65dd98a2867a699) ([merge request](gitlab-org/security/gitlab!2434))
+
## 14.9.4 (2022-04-29)
### Security (15 changes)
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index b1af1ad797b..146255df31f 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -955,7 +955,7 @@ GfmAutoComplete.Milestones = {
};
GfmAutoComplete.Contacts = {
templateFunction({ email, firstName, lastName }) {
- return `<li><small>${firstName} ${lastName}</small> ${escape(email)}</li>`;
+ return `<li><small>${escape(firstName)} ${escape(lastName)}</small> ${escape(email)}</li>`;
},
};
diff --git a/app/assets/javascripts/group_settings/components/shared_runners_form.vue b/app/assets/javascripts/group_settings/components/shared_runners_form.vue
index 3365f4aa76c..06aea26830d 100644
--- a/app/assets/javascripts/group_settings/components/shared_runners_form.vue
+++ b/app/assets/javascripts/group_settings/components/shared_runners_form.vue
@@ -1,8 +1,7 @@
<script>
import { GlToggle, GlAlert } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
-import { __ } from '~/locale';
-import { ERROR_MESSAGE } from '../constants';
+import { I18N_UPDATE_ERROR_MESSAGE, I18N_REFRESH_MESSAGE } from '../constants';
export default {
components: {
@@ -62,8 +61,8 @@ export default {
})
.catch((error) => {
const message = [
- error.response?.data?.error || __('An error occurred while updating configuration.'),
- ERROR_MESSAGE,
+ error.response?.data?.error || I18N_UPDATE_ERROR_MESSAGE,
+ I18N_REFRESH_MESSAGE,
].join(' ');
this.error = message;
diff --git a/app/assets/javascripts/group_settings/constants.js b/app/assets/javascripts/group_settings/constants.js
index ab5c0db45ba..1b44161903d 100644
--- a/app/assets/javascripts/group_settings/constants.js
+++ b/app/assets/javascripts/group_settings/constants.js
@@ -1,3 +1,4 @@
import { __ } from '~/locale';
-export const ERROR_MESSAGE = __('Refresh the page and try again.');
+export const I18N_UPDATE_ERROR_MESSAGE = __('An error occurred while updating configuration.');
+export const I18N_REFRESH_MESSAGE = __('Refresh the page and try again.');
diff --git a/app/assets/javascripts/group_settings/stale_runner_cleanup.js b/app/assets/javascripts/group_settings/stale_runner_cleanup.js
new file mode 100644
index 00000000000..3a4c171915f
--- /dev/null
+++ b/app/assets/javascripts/group_settings/stale_runner_cleanup.js
@@ -0,0 +1,3 @@
+export default () => {
+ // Overridden in EE
+};
diff --git a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
index 52add416f38..bf77d968e7d 100644
--- a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
+++ b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
@@ -1,3 +1,4 @@
+import initStaleRunnerCleanupSetting from 'ee_else_ce/group_settings/stale_runner_cleanup';
import initVariableList from '~/ci_variable_list';
import initSharedRunnersForm from '~/group_settings/mount_shared_runners';
import initSettingsPanels from '~/settings_panels';
@@ -6,4 +7,5 @@ import initSettingsPanels from '~/settings_panels';
initSettingsPanels();
initSharedRunnersForm();
+initStaleRunnerCleanupSetting();
initVariableList();
diff --git a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue
index 8b293b2e9f6..29c1c6bfa9e 100644
--- a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue
+++ b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue
@@ -1,10 +1,5 @@
<script>
-import {
- GlAlert,
- GlKeysetPagination,
- GlDeprecatedSkeletonLoading as GlSkeletonLoading,
- GlPagination,
-} from '@gitlab/ui';
+import { GlAlert, GlKeysetPagination, GlSkeletonLoader, GlPagination } from '@gitlab/ui';
import { uniqueId } from 'lodash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { updateHistory, setUrlParams } from '~/lib/utils/url_utility';
@@ -27,7 +22,7 @@ export default {
components: {
GlAlert,
GlKeysetPagination,
- GlSkeletonLoading,
+ GlSkeletonLoader,
IssuableTabs,
FilteredSearchBar,
IssuableItem,
@@ -307,7 +302,7 @@ export default {
</issuable-bulk-edit-sidebar>
<ul v-if="issuablesLoading" class="content-list">
<li v-for="n in skeletonItemCount" :key="n" class="issue gl-px-5! gl-py-5!">
- <gl-skeleton-loading />
+ <gl-skeleton-loader />
</li>
</ul>
<template v-else>
diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb
index bf72ade32d0..aec3247f4b2 100644
--- a/app/controllers/groups/application_controller.rb
+++ b/app/controllers/groups/application_controller.rb
@@ -67,6 +67,12 @@ class Groups::ApplicationController < ApplicationController
end
end
+ def authorize_read_group_member!
+ unless can?(current_user, :read_group_member, group)
+ render_403
+ end
+ end
+
def build_canonical_path(group)
params[:group_id] = group.to_param
diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb
index 282adcf878b..2748d57748d 100644
--- a/app/controllers/groups/group_members_controller.rb
+++ b/app/controllers/groups/group_members_controller.rb
@@ -14,6 +14,7 @@ class Groups::GroupMembersController < Groups::ApplicationController
# Authorize
before_action :authorize_admin_group_member!, except: admin_not_required_endpoints
+ before_action :authorize_read_group_member!, only: :index
skip_before_action :check_two_factor_requirement, only: :leave
skip_cross_project_access_check :index, :update, :destroy, :request_access,
diff --git a/app/policies/ci/build_policy.rb b/app/policies/ci/build_policy.rb
index 6162a31c118..f377ff85b5e 100644
--- a/app/policies/ci/build_policy.rb
+++ b/app/policies/ci/build_policy.rb
@@ -84,7 +84,7 @@ module Ci
enable :update_commit_status
end
- rule { can?(:update_build) & terminal }.enable :create_build_terminal
+ rule { can?(:update_build) & terminal & owner_of_job }.enable :create_build_terminal
rule { can?(:update_build) }.enable :play_job
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index a4600c720a3..9aae295aea7 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -23,6 +23,7 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
condition(:parent_share_with_group_locked, scope: :subject) { @subject.parent&.share_with_group_lock? }
condition(:can_change_parent_share_with_group_lock) { can?(:change_share_with_group_lock, @subject.parent) }
condition(:migration_bot, scope: :user) { @user.migration_bot? }
+ condition(:can_read_group_member) { can_read_group_member? }
desc "User is a project bot"
condition(:project_bot) { user.project_bot? && access_level >= GroupMember::GUEST }
@@ -128,6 +129,10 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
rule { ~public_group & ~has_access }.prevent :read_counts
+ rule { ~can_read_group_member }.policy do
+ prevent :read_group_member
+ end
+
rule { ~can?(:read_group) }.policy do
prevent :read_design_activity
end
@@ -316,6 +321,10 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
true
end
+ def can_read_group_member?
+ !(@subject.private? && access_level == GroupMember::NO_ACCESS)
+ end
+
def resource_access_token_creation_allowed?
resource_access_token_feature_available? && group.root_ancestor.namespace_settings.resource_access_token_creation_allowed?
end
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 17235034aa5..dac7fe161ed 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -758,6 +758,10 @@ class ProjectPolicy < BasePolicy
prevent :register_project_runners
end
+ rule { can?(:admin_project_member) }.policy do
+ enable :import_project_members_from_another_project
+ end
+
private
def user_is_user?
diff --git a/app/services/ci/pipeline_trigger_service.rb b/app/services/ci/pipeline_trigger_service.rb
index 06eb1aee8e6..39ac9bf33e9 100644
--- a/app/services/ci/pipeline_trigger_service.rb
+++ b/app/services/ci/pipeline_trigger_service.rb
@@ -27,6 +27,7 @@ module Ci
def create_pipeline_from_trigger(trigger)
# this check is to not leak the presence of the project if user cannot read it
return unless trigger.project == project
+ return unless can?(trigger.owner, :read_project, project)
response = Ci::CreatePipelineService
.new(project, trigger.owner, ref: params[:ref], variables_attributes: variables)
diff --git a/app/services/members/import_project_team_service.rb b/app/services/members/import_project_team_service.rb
index 5f4d5414cfa..6efd65e2575 100644
--- a/app/services/members/import_project_team_service.rb
+++ b/app/services/members/import_project_team_service.rb
@@ -29,7 +29,7 @@ module Members
def import_project_team
return false unless target_project.present? && source_project.present? && current_user.present?
return false unless can?(current_user, :read_project_member, source_project)
- return false unless can?(current_user, :admin_project_member, target_project)
+ return false unless can?(current_user, :import_project_members_from_another_project, target_project)
target_project.team.import(source_project, current_user)
end
diff --git a/app/views/groups/runners/_settings.html.haml b/app/views/groups/runners/_settings.html.haml
index 7716a2f125f..5e360ad7b29 100644
--- a/app/views/groups/runners/_settings.html.haml
+++ b/app/views/groups/runners/_settings.html.haml
@@ -1,5 +1,8 @@
-.gl-mb-6
+.gl-mb-5
#update-shared-runners-form{ data: group_shared_runners_settings_data(@group) }
+- if Feature.enabled?(:stale_runner_cleanup_for_namespace_development, @group) && @group.licensed_feature_available?(:stale_runner_cleanup_for_namespace)
+ .gl-mb-5
+ #stale-runner-cleanup-form{ data: { group_full_path: @group.full_path, stale_timeout_secs: ::Ci::Runner::STALE_TIMEOUT.to_i } }
.gl-card.gl-px-8.gl-py-6.gl-line-height-20
.gl-card-body.gl-display-flex{ :class => "gl-p-0!" }
.gl-banner-illustration
diff --git a/config/feature_flags/development/stale_runner_cleanup_for_namespace_development.yml b/config/feature_flags/development/stale_runner_cleanup_for_namespace_development.yml
new file mode 100644
index 00000000000..ae4397cd8a2
--- /dev/null
+++ b/config/feature_flags/development/stale_runner_cleanup_for_namespace_development.yml
@@ -0,0 +1,8 @@
+---
+name: stale_runner_cleanup_for_namespace_development
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87779/
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/363012
+milestone: '15.1'
+type: development
+group: group::runner
+default_enabled: false
diff --git a/doc/administration/package_information/postgresql_versions.md b/doc/administration/package_information/postgresql_versions.md
index 065af020d8d..8aab4121a0b 100644
--- a/doc/administration/package_information/postgresql_versions.md
+++ b/doc/administration/package_information/postgresql_versions.md
@@ -21,6 +21,9 @@ For example:
[Find out which versions of PostgreSQL (and other components) ship with
each Omnibus GitLab release](https://gitlab-org.gitlab.io/omnibus-gitlab/licenses.html).
+The lowest supported PostgreSQL versions are listed in the
+[installation requirements](../../install/requirements.md#postgresql-requirements).
+
Read more about update policies and warnings in the PostgreSQL
[upgrade docs](https://docs.gitlab.com/omnibus/settings/database.html#upgrade-packaged-postgresql-server).
diff --git a/doc/api/scim.md b/doc/api/scim.md
index ab3a181f5be..9c88997b94c 100644
--- a/doc/api/scim.md
+++ b/doc/api/scim.md
@@ -170,13 +170,13 @@ Returns a `201` status code if successful.
Fields that can be updated are:
-| SCIM/IdP field | GitLab field |
-|:---------------------------------|:---------------------------------------|
-| `id/externalId` | `extern_uid` |
-| `name.formatted` | `name` |
-| `emails\[type eq "work"\].value` | `email` |
-| `active` | Identity removal if `active` = `false` |
-| `userName` | `username` |
+| SCIM/IdP field | GitLab field |
+|:---------------------------------|:-----------------------------------------------------------------------------|
+| `id/externalId` | `extern_uid` |
+| `name.formatted` | `name` ([Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/363058)) |
+| `emails\[type eq "work"\].value` | `email` ([Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/363058)) |
+| `active` | Identity removal if `active` = `false` |
+| `userName` | `username` ([Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/363058)) |
```plaintext
PATCH /api/scim/v2/groups/:group_path/Users/:id
diff --git a/doc/ci/runners/configure_runners.md b/doc/ci/runners/configure_runners.md
index 221060f89c5..b39f4493184 100644
--- a/doc/ci/runners/configure_runners.md
+++ b/doc/ci/runners/configure_runners.md
@@ -717,3 +717,47 @@ variables:
| `ARTIFACT_COMPRESSION_LEVEL` | To adjust compression ratio, set to `fastest`, `fast`, `default`, `slow`, or `slowest`. This setting works with the Fastzip archiver only, so the GitLab Runner feature flag [`FF_USE_FASTZIP`](https://docs.gitlab.com/runner/configuration/feature-flags.html#available-feature-flags) must also be enabled. |
| `CACHE_COMPRESSION_LEVEL` | To adjust compression ratio, set to `fastest`, `fast`, `default`, `slow`, or `slowest`. This setting works with the Fastzip archiver only, so the GitLab Runner feature flag [`FF_USE_FASTZIP`](https://docs.gitlab.com/runner/configuration/feature-flags.html#available-feature-flags) must also be enabled. |
| `CACHE_REQUEST_TIMEOUT` | Configure the maximum duration of cache upload and download operations for a single job in minutes. Default is `10` minutes. |
+
+## Clean up stale runners
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/363012) in GitLab 15.1 [with a flag](../../administration/feature_flags.md) named `stale_runner_cleanup_for_namespace_development`. Disabled by default.
+
+FLAG:
+On self-managed GitLab, by default this feature is not available. To make it available per group,
+ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `stale_runner_cleanup_for_namespace_development`.
+
+You can clean up group runners that have been inactive for more than three months.
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Settings > CI/CD**.
+1. Expand **Runners**.
+1. Turn on the **Enable stale runner cleanup** toggle.
+
+### View stale runner cleanup logs
+
+You can check the [Sidekiq logs](../../administration/logs.md#sidekiq-logs) to see the cleanup result. In Kibana you can use the following query:
+
+```json
+{
+ "query": {
+ "match_phrase": {
+ "json.class.keyword": "Ci::Runners::StaleGroupRunnersPruneCronWorker"
+ }
+ }
+}
+```
+
+Filter entries where stale runners were removed:
+
+```json
+{
+ "query": {
+ "range": {
+ "json.extra.ci_runners_stale_group_runners_prune_cron_worker.total_pruned": {
+ "gte": 1,
+ "lt": null
+ }
+ }
+ }
+}
+```
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index c0a8eecb1db..1a806b633c9 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -117,7 +117,7 @@ with [domain expertise](#domain-experts).
Read the [database review guidelines](database_review.md) for more details.
1. If your merge request includes `~frontend` changes (*1*), it must be
**approved by a [frontend maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_frontend)**.
-1. If your merge request includes user-facing changes (*3*), it must be
+1. If your merge request includes (`~UX`) user-facing changes (*3*), it must be
**approved by a [Product Designer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_reviewers_UX)**.
See the [design and user interface guidelines](contributing/design.md) for details.
1. If your merge request includes adding a new JavaScript library (*1*)...
diff --git a/doc/update/index.md b/doc/update/index.md
index e614a3eec4d..2418f495652 100644
--- a/doc/update/index.md
+++ b/doc/update/index.md
@@ -329,7 +329,7 @@ Find where your version sits in the upgrade path below, and upgrade GitLab
accordingly, while also consulting the
[version-specific upgrade instructions](#version-specific-upgrading-instructions):
-`8.11.Z` -> `8.12.0` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> [`11.11.8`](#1200) -> `12.0.12` -> [`12.1.17`](#1210) -> [`12.10.14`](#12100) -> `13.0.14` -> [`13.1.11`](#1310) -> [`13.8.8`](#1388) -> [`13.12.15`](#13120) -> [`14.0.12`](#1400) -> [`14.9.0`](#1490) -> [latest `14.Y.Z`](https://gitlab.com/gitlab-org/gitlab/-/releases)
+`8.11.Z` -> `8.12.0` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> [`11.11.8`](#1200) -> `12.0.12` -> [`12.1.17`](#1210) -> [`12.10.14`](#12100) -> `13.0.14` -> [`13.1.11`](#1310) -> [`13.8.8`](#1388) -> [`13.12.15`](#13120) -> [`14.0.12`](#1400) -> [`14.9.0`](#1490) -> [`14.10.Z`](#1410) -> [`15.0.Z`](#1500) -> [latest `15.Y.Z`](https://gitlab.com/gitlab-org/gitlab/-/releases)
The following table, while not exhaustive, shows some examples of the supported
upgrade paths.
@@ -337,7 +337,9 @@ Additional steps between the mentioned versions are possible. We list the minima
| Target version | Your version | Supported upgrade path | Note |
| -------------- | ------------ | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
-| `14.6.2` | `13.10.2` | `13.10.2` -> `13.12.15` -> `14.0.12` -> `14.6.2` | Two intermediate versions are required: `13.12` and `14.0`, then `14.6.2`. |
+| `15.1.0` | `14.6.2` | `14.6.2` -> `14.9.4` -> `14.10.3` -> `15.0.0` -> `15.1.0` | Three intermediate versions are required: `14.9` and `14.10`, `15.0`, then `15.1.0`. |
+| `15.0.0` | `14.6.2` | `14.6.2` -> `14.9.4` -> `14.10.3` -> `15.0.0` | Two intermediate versions are required: `14.9` and `14.10`, then `15.0.0`. |
+| `14.6.2` | `13.10.2` | `13.10.2` -> `13.12.15` -> `14.0.12` -> `14.6.2` | Two intermediate versions are required: `13.12` and `14.0`, then `14.6.2`. |
| `14.1.8` | `13.9.2` | `13.9.2` -> `13.12.15` -> `14.0.12` -> `14.1.8` | Two intermediate versions are required: `13.12` and `14.0`, then `14.1.8`. |
| `13.12.15` | `12.9.2` | `12.9.2` -> `12.10.14` -> `13.0.14` -> `13.1.11` -> `13.8.8` -> `13.12.15` | Four intermediate versions are required: `12.10`, `13.0`, `13.1` and `13.8.8`, then `13.12.15`. |
| `13.2.10` | `11.5.0` | `11.5.0` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` -> `13.0.14` -> `13.1.11` -> `13.2.10` | Six intermediate versions are required: `11.11`, `12.0`, `12.1`, `12.10`, `13.0` and `13.1`, then `13.2.10`. |
diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md
index 2cddbaa9723..5f3c859d15a 100644
--- a/doc/user/group/subgroups/index.md
+++ b/doc/user/group/subgroups/index.md
@@ -93,6 +93,9 @@ For more information, view the [permissions table](../../permissions.md#group-me
## Subgroup membership
+NOTE:
+There is a bug that causes some pages in the parent group to be accessible by subgroup members. For more details, see [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/340421).
+
When you add a member to a group, that member is also added to all subgroups. The user's permissions are inherited from
the group's parent.
diff --git a/lib/api/helpers/members_helpers.rb b/lib/api/helpers/members_helpers.rb
index c91e153c7b9..6a3cf5c87ae 100644
--- a/lib/api/helpers/members_helpers.rb
+++ b/lib/api/helpers/members_helpers.rb
@@ -15,6 +15,10 @@ module API
public_send("find_#{source_type}!", id) # rubocop:disable GitlabSecurity/PublicSend
end
+ def authorize_read_source_member!(source_type, source)
+ authorize! :"read_#{source_type}_member", source
+ end
+
def authorize_admin_source!(source_type, source)
authorize! :"admin_#{source_type}", source
end
diff --git a/lib/api/members.rb b/lib/api/members.rb
index e2045c6def7..b94f68f60b5 100644
--- a/lib/api/members.rb
+++ b/lib/api/members.rb
@@ -32,6 +32,8 @@ module API
get ":id/members", feature_category: feature_category do
source = find_source(source_type, params[:id])
+ authorize_read_source_member!(source_type, source)
+
members = paginate(retrieve_members(source, params: params))
present_members members
@@ -51,6 +53,8 @@ module API
get ":id/members/all", feature_category: feature_category do
source = find_source(source_type, params[:id])
+ authorize_read_source_member!(source_type, source)
+
members = paginate(retrieve_members(source, params: params, deep: true))
present_members members
@@ -66,6 +70,8 @@ module API
get ":id/members/:user_id", feature_category: feature_category do
source = find_source(source_type, params[:id])
+ authorize_read_source_member!(source_type, source)
+
members = source_members(source)
member = members.find_by!(user_id: params[:user_id])
@@ -83,6 +89,8 @@ module API
get ":id/members/all/:user_id", feature_category: feature_category do
source = find_source(source_type, params[:id])
+ authorize_read_source_member!(source_type, source)
+
members = find_all_members(source)
member = members.find_by!(user_id: params[:user_id])
diff --git a/lib/sidebars/projects/menus/monitor_menu.rb b/lib/sidebars/projects/menus/monitor_menu.rb
index 311c44f5f80..c35bc1f5481 100644
--- a/lib/sidebars/projects/menus/monitor_menu.rb
+++ b/lib/sidebars/projects/menus/monitor_menu.rb
@@ -10,6 +10,7 @@ module Sidebars
add_item(metrics_dashboard_menu_item)
add_item(logs_menu_item)
+ add_item(tracing_menu_item)
add_item(error_tracking_menu_item)
add_item(alert_management_menu_item)
add_item(incidents_menu_item)
@@ -71,6 +72,21 @@ module Sidebars
)
end
+ def tracing_menu_item
+ if !Feature.enabled?(:monitor_tracing, context.project) ||
+ !can?(context.current_user, :read_environment, context.project) ||
+ !can?(context.current_user, :admin_project, context.project)
+ return ::Sidebars::NilMenuItem.new(item_id: :tracing)
+ end
+
+ ::Sidebars::MenuItem.new(
+ title: _('Tracing'),
+ link: project_tracing_path(context.project),
+ active_routes: { path: 'tracings#show' },
+ item_id: :tracing
+ )
+ end
+
def error_tracking_menu_item
unless can?(context.current_user, :read_sentry_issue, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :error_tracking)
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index fde3aa3e9c0..6a7621557f2 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -32668,12 +32668,18 @@ msgstr[1] ""
msgid "Runners|A capacity of 1 enables warm HA through Auto Scaling group re-spawn. A capacity of 2 enables hot HA because the service is available even when a node is lost. A capacity of 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|A periodic background task deletes runners that haven't contacted GitLab in more than %{elapsedTime}. %{linkStart}Can I view how many runners were deleted?%{linkEnd}"
+msgstr ""
+
msgid "Runners|Active"
msgstr ""
msgid "Runners|All"
msgstr ""
+msgid "Runners|All group runners that have not contacted GitLab in more than %{elapsedTime} are deleted permanently. This task runs periodically in the background."
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -32760,6 +32766,12 @@ msgstr ""
msgid "Runners|Download latest binary"
msgstr ""
+msgid "Runners|Enable stale runner cleanup"
+msgstr ""
+
+msgid "Runners|Enable stale runner cleanup?"
+msgstr ""
+
msgid "Runners|Enter the number of seconds. This timeout takes precedence over lower timeouts set for the project."
msgstr ""
@@ -33002,6 +33014,14 @@ msgstr ""
msgid "Runners|The runner will be permanently deleted and no longer available for projects or groups in the instance. Are you sure you want to continue?"
msgstr ""
+msgid "Runners|This group currently has 1 stale runner."
+msgid_plural "Runners|This group currently has %d stale runners."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Runners|This group currently has no stale runners."
+msgstr ""
+
msgid "Runners|This runner has not run any jobs."
msgstr ""
@@ -33044,6 +33064,9 @@ msgstr ""
msgid "Runners|Windows 2019 Shell with manual scaling and optional scheduling. Non-spot."
msgstr ""
+msgid "Runners|Yes, start deleting stale runners"
+msgstr ""
+
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
diff --git a/package.json b/package.json
index cfecb99a3d6..5ba42d4abba 100644
--- a/package.json
+++ b/package.json
@@ -257,7 +257,7 @@
"stylelint": "^14.3.0",
"timezone-mock": "^1.0.8",
"vue-jest": "4.0.1",
- "webpack-dev-server": "4.9.0",
+ "webpack-dev-server": "4.9.1",
"xhr-mock": "^2.5.1",
"yarn-check-webpack-plugin": "^1.2.0",
"yarn-deduplicate": "^5.0.0"
diff --git a/qa/qa/page/project/settings/ci_variables.rb b/qa/qa/page/project/settings/ci_variables.rb
index 2b8fad64afb..e9224fcb159 100644
--- a/qa/qa/page/project/settings/ci_variables.rb
+++ b/qa/qa/page/project/settings/ci_variables.rb
@@ -21,7 +21,7 @@ module QA
element :reveal_ci_variable_value_button
end
- def fill_variable(key, value, masked)
+ def fill_variable(key, value, masked = false)
within_element(:ci_variable_key_field) { find('input').set key }
fill_element :ci_variable_value_field, value
click_ci_variable_save_button
diff --git a/qa/qa/specs/features/browser_ui/4_verify/testing/endpoint_coverage_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/testing/endpoint_coverage_spec.rb
new file mode 100644
index 00000000000..adcf91a550c
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/4_verify/testing/endpoint_coverage_spec.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+module QA
+ # Spark various endpoints (git, web, api, sidekiq) to ensure
+ # GitLab-QA covers these various endpoints. The `api_json.log` can then be consumed after test run.
+ #
+ # User sets a CI variable via UI (Web write) ->
+ # Git push (Git read/write) ->
+ # pipeline created (Sidekiq read/write) ->
+ # runner picks up pipeline (API read/write) ->
+ # User views pipeline succeeds (Web read)
+ RSpec.describe 'Verify', :runner do
+ context 'Endpoint Coverage' do
+ let!(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'endpoint-coverage'
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate_via_api! do |runner|
+ runner.project = project
+ runner.name = project.name
+ runner.tags = [project.name]
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ project.visit!
+ end
+
+ after do
+ project.remove_via_api!
+ runner.remove_via_api!
+ end
+
+ it(
+ 'spans r/w postgres web sidekiq git api',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/360837'
+ ) do
+ # create a CI variable via UI
+ Page::Project::Show.perform(&:go_to_ci_cd_settings)
+
+ Page::Project::Settings::CiCd.perform do |ci_cd|
+ ci_cd.expand_ci_variables do |vars|
+ vars.click_add_variable
+ vars.fill_variable('CI_VARIABLE', 'secret-value')
+ end
+ end
+
+ # push a .gitlab-ci.yml file that exposes artifacts
+ Resource::Repository::ProjectPush.fabricate! do |push|
+ push.project = project
+ push.file_name = '.gitlab-ci.yml'
+ push.file_content = <<~YAML
+ test:
+ tags:
+ - #{project.name}
+ script:
+ - mkdir out; echo $CI_VARIABLE > out/file.out
+ artifacts:
+ paths:
+ - out/
+ expire_in: 1h
+ YAML
+ push.commit_message = 'Commit .gitlab-ci.yml'
+ end
+
+ # observe pipeline creation
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |show|
+ show.click_job('test')
+ end
+
+ Page::Project::Job::Show.perform do |show|
+ # user views job succeeding
+ expect { show.passed? }.to eventually_be_truthy.within(max_duration: 60, sleep_interval: 1)
+
+ show.click_browse_button
+ end
+
+ Page::Project::Artifact::Show.perform do |show|
+ show.go_to_directory('out')
+ expect(show).to have_content('file.out')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb
index 5aafddd94da..107eb1ed3a3 100644
--- a/spec/controllers/projects/jobs_controller_spec.rb
+++ b/spec/controllers/projects/jobs_controller_spec.rb
@@ -183,7 +183,7 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
context 'with web terminal' do
- let(:job) { create(:ci_build, :running, :with_runner_session, pipeline: pipeline) }
+ let(:job) { create(:ci_build, :running, :with_runner_session, pipeline: pipeline, user: user) }
it 'exposes the terminal path' do
expect(response).to have_gitlab_http_status(:ok)
@@ -1303,7 +1303,7 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
context 'when job exists' do
context 'and it has a terminal' do
- let!(:job) { create(:ci_build, :running, :with_runner_session, pipeline: pipeline) }
+ let!(:job) { create(:ci_build, :running, :with_runner_session, pipeline: pipeline, user: user) }
it 'has a job' do
get_terminal(id: job.id)
@@ -1314,7 +1314,7 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
context 'and does not have a terminal' do
- let!(:job) { create(:ci_build, :running, pipeline: pipeline) }
+ let!(:job) { create(:ci_build, :running, pipeline: pipeline, user: user) }
it 'returns not_found' do
get_terminal(id: job.id)
@@ -1343,7 +1343,7 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
describe 'GET #terminal_websocket_authorize' do
- let!(:job) { create(:ci_build, :running, :with_runner_session, pipeline: pipeline) }
+ let!(:job) { create(:ci_build, :running, :with_runner_session, pipeline: pipeline, user: user) }
before do
project.add_developer(user)
diff --git a/spec/features/security/group/private_access_spec.rb b/spec/features/security/group/private_access_spec.rb
index fc1fb3e3848..f733145b5e3 100644
--- a/spec/features/security/group/private_access_spec.rb
+++ b/spec/features/security/group/private_access_spec.rb
@@ -97,7 +97,7 @@ RSpec.describe 'Private Group access' do
it { is_expected.to be_allowed_for(:developer).of(group) }
it { is_expected.to be_allowed_for(:reporter).of(group) }
it { is_expected.to be_allowed_for(:guest).of(group) }
- it { is_expected.to be_allowed_for(project_guest) }
+ it { is_expected.to be_denied_for(project_guest) }
it { is_expected.to be_denied_for(:user) }
it { is_expected.to be_denied_for(:external) }
it { is_expected.to be_denied_for(:visitor) }
diff --git a/spec/frontend/gfm_auto_complete_spec.js b/spec/frontend/gfm_auto_complete_spec.js
index aa98b2774ea..552377e3381 100644
--- a/spec/frontend/gfm_auto_complete_spec.js
+++ b/spec/frontend/gfm_auto_complete_spec.js
@@ -868,4 +868,19 @@ describe('GfmAutoComplete', () => {
);
});
});
+
+ describe('Contacts', () => {
+ it('escapes name and email correct', () => {
+ const xssPayload = '<script>alert(1)</script>';
+ const escapedPayload = '&lt;script&gt;alert(1)&lt;/script&gt;';
+
+ expect(
+ GfmAutoComplete.Contacts.templateFunction({
+ email: xssPayload,
+ firstName: xssPayload,
+ lastName: xssPayload,
+ }),
+ ).toBe(`<li><small>${escapedPayload} ${escapedPayload}</small> ${escapedPayload}</li>`);
+ });
+ });
});
diff --git a/spec/frontend/runner/components/__snapshots__/runner_status_popover_spec.js.snap b/spec/frontend/runner/components/__snapshots__/runner_status_popover_spec.js.snap
index 80a04401760..b27a1adf01b 100644
--- a/spec/frontend/runner/components/__snapshots__/runner_status_popover_spec.js.snap
+++ b/spec/frontend/runner/components/__snapshots__/runner_status_popover_spec.js.snap
@@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`RunnerStatusPopover renders complete text 1`] = `"Never contacted: Runner has never contacted GitLab (when you register a runner, use gitlab-runner run to bring it online) Online: Runner has contacted GitLab within the last 2 hours Offline: Runner has not contacted GitLab in more than 2 hours Stale: Runner has not contacted GitLab in more than 2 months"`;
+exports[`RunnerStatusPopover renders complete text 1`] = `"Never contacted: Runner has never contacted GitLab (when you register a runner, use gitlab-runner run to bring it online) Online: Runner has contacted GitLab within the last 2 hours Offline: Runner has not contacted GitLab in more than 2 hours Stale: Runner has not contacted GitLab in more than 3 months"`;
diff --git a/spec/frontend/runner/mock_data.js b/spec/frontend/runner/mock_data.js
index 1c2333b552c..40854dae57a 100644
--- a/spec/frontend/runner/mock_data.js
+++ b/spec/frontend/runner/mock_data.js
@@ -19,7 +19,7 @@ import groupRunnersCountData from 'test_fixtures/graphql/runner/list/group_runne
// Other mock data
export const onlineContactTimeoutSecs = 2 * 60 * 60;
-export const staleTimeoutSecs = 5259492; // Ruby's `2.months`
+export const staleTimeoutSecs = 7889238; // Ruby's `3.months`
export {
runnersData,
diff --git a/spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js b/spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js
index 058cb30c1d5..66f71c0b028 100644
--- a/spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js
+++ b/spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js
@@ -1,9 +1,4 @@
-import {
- GlAlert,
- GlKeysetPagination,
- GlDeprecatedSkeletonLoading as GlSkeletonLoading,
- GlPagination,
-} from '@gitlab/ui';
+import { GlAlert, GlKeysetPagination, GlSkeletonLoader, GlPagination } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import VueDraggable from 'vuedraggable';
@@ -263,7 +258,7 @@ describe('IssuableListRoot', () => {
it('renders gl-loading-icon when `issuablesLoading` prop is true', () => {
wrapper = createComponent({ props: { issuablesLoading: true } });
- expect(wrapper.findAllComponents(GlSkeletonLoading)).toHaveLength(
+ expect(wrapper.findAllComponents(GlSkeletonLoader)).toHaveLength(
wrapper.vm.skeletonItemCount,
);
});
diff --git a/spec/helpers/emails_helper_spec.rb b/spec/helpers/emails_helper_spec.rb
index 39b919fa925..969ef6cae7f 100644
--- a/spec/helpers/emails_helper_spec.rb
+++ b/spec/helpers/emails_helper_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe EmailsHelper do
+ include EmailsHelperTestHelper
+
describe 'closure_reason_text' do
context 'when given a MergeRequest' do
let(:merge_request) { create(:merge_request) }
@@ -238,17 +240,13 @@ RSpec.describe EmailsHelper do
it 'returns the default header logo' do
create :appearance, header_logo: nil
- expect(header_logo).to match(
- %r{<img alt="GitLab" src="/images/mailers/gitlab_logo\.(?:gif|png)" width="\d+" height="\d+" />}
- )
+ expect(header_logo).to match(default_header_logo)
end
end
context 'there is no brand item' do
it 'returns the default header logo' do
- expect(header_logo).to match(
- %r{<img alt="GitLab" src="/images/mailers/gitlab_logo\.(?:gif|png)" width="\d+" height="\d+" />}
- )
+ expect(header_logo).to match(default_header_logo)
end
end
end
diff --git a/spec/lib/sidebars/projects/menus/monitor_menu_spec.rb b/spec/lib/sidebars/projects/menus/monitor_menu_spec.rb
index 9d5845d20e5..b11c9db4e46 100644
--- a/spec/lib/sidebars/projects/menus/monitor_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/monitor_menu_spec.rb
@@ -82,6 +82,20 @@ RSpec.describe Sidebars::Projects::Menus::MonitorMenu do
end
end
+ describe 'Tracing' do
+ let(:item_id) { :tracing }
+
+ it_behaves_like 'access rights checks'
+
+ context 'when feature disabled' do
+ before do
+ stub_feature_flags(monitor_tracing: false)
+ end
+
+ specify { is_expected.to be_nil }
+ end
+ end
+
describe 'Error Tracking' do
let(:item_id) { :error_tracking }
diff --git a/spec/policies/ci/build_policy_spec.rb b/spec/policies/ci/build_policy_spec.rb
index 1ec749fb394..fee4d76ca8f 100644
--- a/spec/policies/ci/build_policy_spec.rb
+++ b/spec/policies/ci/build_policy_spec.rb
@@ -405,4 +405,52 @@ RSpec.describe Ci::BuildPolicy do
end
end
end
+
+ describe 'ability :create_build_terminal' do
+ let(:project) { create(:project, :private) }
+
+ subject { described_class.new(user, build) }
+
+ context 'when user can update_build' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ context 'when job has terminal' do
+ before do
+ allow(build).to receive(:has_terminal?).and_return(true)
+ end
+
+ context 'when current user is the job owner' do
+ before do
+ build.update!(user: user)
+ end
+
+ it { expect_allowed(:create_build_terminal) }
+ end
+
+ context 'when current user is not the job owner' do
+ it { expect_disallowed(:create_build_terminal) }
+ end
+ end
+
+ context 'when job does not have terminal' do
+ before do
+ allow(build).to receive(:has_terminal?).and_return(false)
+ build.update!(user: user)
+ end
+
+ it { expect_disallowed(:create_build_terminal) }
+ end
+ end
+
+ context 'when user cannot update build' do
+ before do
+ project.add_guest(user)
+ allow(build).to receive(:has_terminal?).and_return(true)
+ end
+
+ it { expect_disallowed(:create_build_terminal) }
+ end
+ end
end
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index ce97fc0c77e..d9316344474 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -396,6 +396,36 @@ RSpec.describe ProjectPolicy do
end
end
+ context 'importing members from another project' do
+ %w(maintainer owner).each do |role|
+ context "with #{role}" do
+ let(:current_user) { send(role) }
+
+ it { is_expected.to be_allowed(:import_project_members_from_another_project) }
+ end
+ end
+
+ %w(guest reporter developer anonymous).each do |role|
+ context "with #{role}" do
+ let(:current_user) { send(role) }
+
+ it { is_expected.to be_disallowed(:import_project_members_from_another_project) }
+ end
+ end
+
+ context 'with an admin' do
+ let(:current_user) { admin }
+
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it { expect_allowed(:import_project_members_from_another_project) }
+ end
+
+ context 'when admin mode is disabled' do
+ it { expect_disallowed(:import_project_members_from_another_project) }
+ end
+ end
+ end
+
context 'reading usage quotas' do
%w(maintainer owner).each do |role|
context "with #{role}" do
diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb
index 94f1bf13830..e4c2f17af47 100644
--- a/spec/requests/api/members_spec.rb
+++ b/spec/requests/api/members_spec.rb
@@ -185,6 +185,21 @@ RSpec.describe API::Members do
expect(json_response).to be_an Array
expect(json_response.map { |u| u['id'] }).to match_array [maintainer.id, developer.id, nested_user.id]
end
+
+ context 'with a subgroup' do
+ let(:group) { create(:group, :private)}
+ let(:subgroup) { create(:group, :private, parent: group)}
+ let(:project) { create(:project, group: subgroup) }
+
+ before do
+ subgroup.add_developer(developer)
+ end
+
+ it 'subgroup member cannot get parent group members list' do
+ get api("/groups/#{group.id}/members/all", developer)
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
end
shared_examples 'GET /:source_type/:id/members/(all/):user_id' do |source_type, all|
diff --git a/spec/services/ci/pipeline_trigger_service_spec.rb b/spec/services/ci/pipeline_trigger_service_spec.rb
index a794dedc658..4b3e774ff3c 100644
--- a/spec/services/ci/pipeline_trigger_service_spec.rb
+++ b/spec/services/ci/pipeline_trigger_service_spec.rb
@@ -56,6 +56,15 @@ RSpec.describe Ci::PipelineTriggerService do
end
end
+ context 'when trigger owner does not have a permission to read a project' do
+ let(:params) { { token: trigger.token, ref: 'master', variables: nil } }
+ let(:trigger) { create(:ci_trigger, project: project, owner: create(:user)) }
+
+ it 'does nothing' do
+ expect { result }.not_to change { Ci::Pipeline.count }
+ end
+ end
+
context 'when params have an existing trigger token' do
context 'when params have an existing ref' do
let(:params) { { token: trigger.token, ref: 'master', variables: nil } }
diff --git a/spec/support/helpers/emails_helper_test_helper.rb b/spec/support/helpers/emails_helper_test_helper.rb
new file mode 100644
index 00000000000..ea7dbc89ebd
--- /dev/null
+++ b/spec/support/helpers/emails_helper_test_helper.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module EmailsHelperTestHelper
+ def default_header_logo
+ %r{<img alt="GitLab" src="/images/mailers/gitlab_logo\.(?:gif|png)" width="\d+" height="\d+" />}
+ end
+end
+
+EmailsHelperTestHelper.prepend_mod
diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb
index 50e6d4aad1b..d277a45584d 100644
--- a/spec/support/shared_contexts/navbar_structure_context.rb
+++ b/spec/support/shared_contexts/navbar_structure_context.rb
@@ -84,6 +84,7 @@ RSpec.shared_context 'project navbar structure' do
nav_sub_items: [
_('Metrics'),
_('Logs'),
+ _('Tracing'),
_('Error Tracking'),
_('Alerts'),
_('Incidents'),
diff --git a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
index 7f961b3a4e9..3943355bffd 100644
--- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
+++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
@@ -437,6 +437,32 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end
end
+ describe 'Tracing' do
+ it 'has a link to the tracing page' do
+ render
+
+ expect(rendered).to have_link('Tracing', href: project_tracing_path(project))
+ end
+
+ context 'without project.tracing_external_url' do
+ it 'has a link to the tracing page' do
+ render
+
+ expect(rendered).to have_link('Tracing', href: project_tracing_path(project))
+ end
+ end
+
+ describe 'when the user does not have access' do
+ let(:user) { nil }
+
+ it 'does not have a link to the tracing page' do
+ render
+
+ expect(rendered).not_to have_text 'Tracing'
+ end
+ end
+ end
+
describe 'Error Tracking' do
it 'has a link to the error tracking page' do
render
diff --git a/yarn.lock b/yarn.lock
index 93a468ab58c..89d0f32870c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -11313,13 +11313,13 @@ snapdragon@^0.8.1:
source-map-resolve "^0.5.0"
use "^3.1.0"
-sockjs@^0.3.21:
- version "0.3.21"
- resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417"
- integrity sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==
+sockjs@^0.3.24:
+ version "0.3.24"
+ resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce"
+ integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==
dependencies:
faye-websocket "^0.11.3"
- uuid "^3.4.0"
+ uuid "^8.3.2"
websocket-driver "^0.7.4"
sortablejs@^1.10.2, sortablejs@^1.9.0:
@@ -12508,15 +12508,15 @@ uuid@8.1.0:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.1.0.tgz#6f1536eb43249f473abc6bd58ff983da1ca30d8d"
integrity sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg==
-uuid@^3.3.2, uuid@^3.3.3, uuid@^3.4.0:
+uuid@^3.3.2, uuid@^3.3.3:
version "3.4.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
-uuid@^8.3.0:
- version "8.3.1"
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31"
- integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==
+uuid@^8.3.0, uuid@^8.3.2:
+ version "8.3.2"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
+ integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
uvu@^0.5.0:
version "0.5.3"
@@ -12926,10 +12926,10 @@ webpack-dev-middleware@^5.3.1:
range-parser "^1.2.1"
schema-utils "^4.0.0"
-webpack-dev-server@4.9.0:
- version "4.9.0"
- resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.9.0.tgz#737dbf44335bb8bde68f8f39127fc401c97a1557"
- integrity sha512-+Nlb39iQSOSsFv0lWUuUTim3jDQO8nhK3E68f//J2r5rIcp4lULHXz2oZ0UVdEeWXEh5lSzYUlzarZhDAeAVQw==
+webpack-dev-server@4.9.1:
+ version "4.9.1"
+ resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.9.1.tgz#184607b0287c791aeaa45e58e8fe75fcb4d7e2a8"
+ integrity sha512-CTMfu2UMdR/4OOZVHRpdy84pNopOuigVIsRbGX3LVDMWNP8EUgC5mUBMErbwBlHTEX99ejZJpVqrir6EXAEajA==
dependencies:
"@types/bonjour" "^3.5.9"
"@types/connect-history-api-fallback" "^1.3.5"
@@ -12955,7 +12955,7 @@ webpack-dev-server@4.9.0:
schema-utils "^4.0.0"
selfsigned "^2.0.1"
serve-index "^1.9.1"
- sockjs "^0.3.21"
+ sockjs "^0.3.24"
spdy "^4.0.2"
webpack-dev-middleware "^5.3.1"
ws "^8.4.2"