Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-06-17 09:08:50 +00:00
parent e4476c4a18
commit 6bbf310347
43 changed files with 237 additions and 274 deletions

View File

@ -15,6 +15,7 @@ const PERSISTENT_USER_CALLOUTS = [
'.js-user-over-limit-free-plan-alert',
'.js-minute-limit-banner',
'.js-submit-license-usage-data-banner',
'.js-project-usage-limitations-callout',
];
const initCallouts = () => {

View File

@ -19,6 +19,9 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
session.delete(:user_return_to)
render "doorkeeper/authorizations/redirect", locals: { redirect_uri: parsed_redirect_uri }, layout: false
else
redirect_uri = URI(authorization.authorize.redirect_uri)
allow_redirect_uri_form_action(redirect_uri.scheme)
render "doorkeeper/authorizations/new"
end
else
@ -28,6 +31,20 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
private
# Chrome blocks redirections if the form-action CSP directive is present
# and the redirect location's scheme isn't allow-listed
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/form-action
# https://github.com/w3c/webappsec-csp/issues/8
def allow_redirect_uri_form_action(redirect_uri_scheme)
return unless content_security_policy?
form_action = request.content_security_policy.form_action
return unless form_action
form_action.push("#{redirect_uri_scheme}:")
request.content_security_policy.form_action(*form_action)
end
def pre_auth_params
# Cannot be achieved with a before_action hook, due to the execution order.
downgrade_scopes! if action_name == 'new'

View File

@ -16,7 +16,7 @@ module Nav
menu_sections.push(general_menu_section)
{
title: _("New..."),
title: _("Create new"),
menu_sections: menu_sections.select { |x| x.fetch(:menu_items).any? }
}
end

View File

@ -137,8 +137,8 @@ module Ci
where('NOT EXISTS (?)', Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id').trace)
end
scope :with_reports, ->(reports_scope) do
with_existing_job_artifacts(reports_scope)
scope :with_artifacts, ->(artifact_scope) do
with_existing_job_artifacts(artifact_scope)
.eager_load_job_artifacts
end
@ -1047,7 +1047,7 @@ module Ci
end
def report_artifacts
job_artifacts.with_reports
job_artifacts.all_reports
end
# Virtual deployment status depending on the environment status.

View File

@ -152,7 +152,7 @@ module Ci
where(file_type: types)
end
scope :with_reports, -> do
scope :all_reports, -> do
with_file_types(REPORT_TYPES.keys.map(&:to_s))
end

View File

@ -342,7 +342,7 @@ module Ci
end
scope :with_reports, -> (reports_scope) do
where('EXISTS (?)', ::Ci::Build.latest.with_reports(reports_scope).where('ci_pipelines.id=ci_builds.commit_id').select(1))
where('EXISTS (?)', ::Ci::Build.latest.with_artifacts(reports_scope).where('ci_pipelines.id=ci_builds.commit_id').select(1))
end
scope :with_only_interruptible_builds, -> do
@ -696,7 +696,7 @@ module Ci
def latest_report_artifacts
::Gitlab::SafeRequestStore.fetch("pipeline:#{self.id}:latest_report_artifacts") do
::Ci::JobArtifact.where(
id: job_artifacts.with_reports
id: job_artifacts.all_reports
.select('max(ci_job_artifacts.id) as id')
.group(:file_type)
)
@ -1057,16 +1057,16 @@ module Ci
@latest_builds_with_artifacts ||= builds.latest.with_artifacts_not_expired.to_a
end
def latest_report_builds(reports_scope = ::Ci::JobArtifact.with_reports)
builds.latest.with_reports(reports_scope)
def latest_report_builds(reports_scope = ::Ci::JobArtifact.all_reports)
builds.latest.with_artifacts(reports_scope)
end
def latest_test_report_builds
latest_report_builds(Ci::JobArtifact.test_reports).preload(:project, :metadata)
end
def latest_report_builds_in_self_and_descendants(reports_scope = ::Ci::JobArtifact.with_reports)
builds_in_self_and_descendants.with_reports(reports_scope)
def latest_report_builds_in_self_and_descendants(reports_scope = ::Ci::JobArtifact.all_reports)
builds_in_self_and_descendants.with_artifacts(reports_scope)
end
def builds_with_coverage

View File

@ -52,7 +52,8 @@ module Users
minute_limit_banner: 49,
preview_user_over_limit_free_plan_alert: 50, # EE-only
user_reached_limit_free_plan_alert: 51, # EE-only
submit_license_usage_data_banner: 52 # EE-only
submit_license_usage_data_banner: 52, # EE-only
personal_project_limitations_banner: 53 # EE-only
}
validates :feature_name,

View File

@ -3,7 +3,7 @@
- verified_at = mirror.ssh_known_hosts_verified_at
.form-group.js-ssh-host-keys-section{ class: ('collapse' unless mirror.ssh_mirror_url?) }
%button.btn.gl-button.btn-inverted.btn-secondary.inline.js-detect-host-keys.gl-mr-3{ type: 'button', data: { qa_selector: 'detect_host_keys' } }
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-detect-host-keys gl-mr-3', data: { qa_selector: 'detect_host_keys' } }) do
= gl_loading_icon(inline: true, css_class: 'js-spinner gl-display-none gl-mr-2')
= _('Detect host keys')
.fingerprint-ssh-info.js-fingerprint-ssh-info.gl-mt-3.gl-mb-3{ class: ('collapse' unless mirror.ssh_mirror_url?) }
@ -23,7 +23,7 @@
#{time_ago_in_words(verified_at)} ago
.js-ssh-hosts-advanced.inline
%button.btn.gl-button.btn-default.btn-show-advanced.show-advanced{ type: 'button' }
= render Pajamas::ButtonComponent.new(button_options: { class: 'btn-show-advanced show-advanced' }) do
%span.label-show
= _('Input host keys manually')
%span.label-hide

View File

@ -1,5 +1,13 @@
- page_title s_("UsageQuota|Usage")
- presenter_class = Namespaces::FreeUserCap::Projects::UsageQuotaLimitationsBannerPresenter
- usage_quota_limits_banner_presenter = presenter_class.new(@project, current_user: current_user)
- if usage_quota_limits_banner_presenter.visible?
= render Pajamas::AlertComponent.new(**usage_quota_limits_banner_presenter.alert_component_attributes) do |c|
- c.body do
= usage_quota_limits_banner_presenter.body_text
= render Pajamas::AlertComponent.new(title: _('Repository usage recalculation started'),
variant: :info,
alert_options: { class: 'js-recalculation-started-alert gl-mt-4 gl-mb-5 gl-display-none' }) do |c|

View File

@ -320,7 +320,7 @@
:tags: []
- :name: cronjob:database_ci_namespace_mirrors_consistency_check
:worker_name: Database::CiNamespaceMirrorsConsistencyCheckWorker
:feature_category: :sharding
:feature_category: :pods
:has_external_dependencies: false
:urgency: :low
:resource_boundary: :unknown
@ -329,7 +329,7 @@
:tags: []
- :name: cronjob:database_ci_project_mirrors_consistency_check
:worker_name: Database::CiProjectMirrorsConsistencyCheckWorker
:feature_category: :sharding
:feature_category: :pods
:has_external_dependencies: false
:urgency: :low
:resource_boundary: :unknown
@ -455,7 +455,7 @@
:tags: []
- :name: cronjob:loose_foreign_keys_cleanup
:worker_name: LooseForeignKeys::CleanupWorker
:feature_category: :sharding
:feature_category: :pods
:has_external_dependencies: false
:urgency: :low
:resource_boundary: :unknown
@ -2625,7 +2625,7 @@
:tags: []
- :name: namespaces_process_sync_events
:worker_name: Namespaces::ProcessSyncEventsWorker
:feature_category: :sharding
:feature_category: :pods
:has_external_dependencies: false
:urgency: :high
:resource_boundary: :unknown
@ -2814,7 +2814,7 @@
:tags: []
- :name: projects_process_sync_events
:worker_name: Projects::ProcessSyncEventsWorker
:feature_category: :sharding
:feature_category: :pods
:has_external_dependencies: false
:urgency: :high
:resource_boundary: :unknown

View File

@ -6,7 +6,7 @@ module Database
include CronjobQueue # rubocop: disable Scalability/CronWorkerContext
sidekiq_options retry: false
feature_category :sharding
feature_category :pods
data_consistency :sticky
idempotent!

View File

@ -6,7 +6,7 @@ module Database
include CronjobQueue # rubocop: disable Scalability/CronWorkerContext
sidekiq_options retry: false
feature_category :sharding
feature_category :pods
data_consistency :sticky
idempotent!

View File

@ -7,7 +7,7 @@ module LooseForeignKeys
include CronjobQueue # rubocop: disable Scalability/CronWorkerContext
sidekiq_options retry: false
feature_category :sharding
feature_category :pods
data_consistency :always
idempotent!

View File

@ -9,7 +9,7 @@ module Namespaces
data_consistency :always
feature_category :sharding
feature_category :pods
urgency :high
idempotent!

View File

@ -9,7 +9,7 @@ module Projects
data_consistency :always
feature_category :sharding
feature_category :pods
urgency :high
idempotent!

View File

@ -90,6 +90,7 @@
- permissions
- pipeline_authoring
- planning_analytics
- pods
- portfolio_management
- privacy_control_center
- product_analytics
@ -114,10 +115,10 @@
- security_orchestration
- service_desk
- service_ping
- sharding
- snippets
- source_code_management
- static_application_security_testing
- static_site_editor
- subgroups
- system_access
- team_planning

View File

@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339181
milestone: '14.3'
type: development
group: group::code review
default_enabled: false
default_enabled: true

View File

@ -0,0 +1,8 @@
---
name: scan_execution_rule_mode
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90099
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/359883
milestone: '15.2'
type: development
group: group::container security
default_enabled: false

View File

@ -11,26 +11,7 @@ class ScheduleMigratePagesToZipStorage < ActiveRecord::Migration[6.0]
disable_ddl_transaction!
class ProjectPagesMetadatum < ActiveRecord::Base
extend SuppressCompositePrimaryKeyWarning
include EachBatch
self.primary_key = :project_id
self.table_name = 'project_pages_metadata'
self.inheritance_column = :_type_disabled
scope :deployed, -> { where(deployed: true) }
scope :only_on_legacy_storage, -> { deployed.where(pages_deployment_id: nil) }
end
def up
queue_background_migration_jobs_by_range_at_intervals(
ProjectPagesMetadatum.only_on_legacy_storage,
MIGRATION,
BATCH_TIME,
batch_size: BATCH_SIZE,
primary_column_name: :project_id
)
# no-op
end
end

View File

@ -19849,6 +19849,7 @@ Name of the feature that the callout is for.
| <a id="usercalloutfeaturenameenumminute_limit_banner"></a>`MINUTE_LIMIT_BANNER` | Callout feature name for minute_limit_banner. |
| <a id="usercalloutfeaturenameenumnew_user_signups_cap_reached"></a>`NEW_USER_SIGNUPS_CAP_REACHED` | Callout feature name for new_user_signups_cap_reached. |
| <a id="usercalloutfeaturenameenumpersonal_access_token_expiry"></a>`PERSONAL_ACCESS_TOKEN_EXPIRY` | Callout feature name for personal_access_token_expiry. |
| <a id="usercalloutfeaturenameenumpersonal_project_limitations_banner"></a>`PERSONAL_PROJECT_LIMITATIONS_BANNER` | Callout feature name for personal_project_limitations_banner. |
| <a id="usercalloutfeaturenameenumpipeline_needs_banner"></a>`PIPELINE_NEEDS_BANNER` | Callout feature name for pipeline_needs_banner. |
| <a id="usercalloutfeaturenameenumpipeline_needs_hover_tip"></a>`PIPELINE_NEEDS_HOVER_TIP` | Callout feature name for pipeline_needs_hover_tip. |
| <a id="usercalloutfeaturenameenumpreview_user_over_limit_free_plan_alert"></a>`PREVIEW_USER_OVER_LIMIT_FREE_PLAN_ALERT` | Callout feature name for preview_user_over_limit_free_plan_alert. |

View File

@ -83,7 +83,8 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77236) in GitLab 14.7.
Create a [group access token](../user/group/settings/group_access_tokens.md).
Create a [group access token](../user/group/settings/group_access_tokens.md). You must have the Owner role for the
group to create group access tokens.
```plaintext
POST groups/:id/access_tokens
@ -94,7 +95,7 @@ POST groups/:id/access_tokens
| `id` | integer or string | yes | ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
| `name` | String | yes | Name of the group access token |
| `scopes` | `Array[String]` | yes | [List of scopes](../user/group/settings/group_access_tokens.md#scopes-for-a-group-access-token) |
| `access_level` | Integer | no | A valid access level. Default value is 40 (Maintainer). Other allowed values are 10 (Guest), 20 (Reporter), and 30 (Developer). |
| `access_level` | Integer | no | Access level. Valid values are `10` (Guest), `20` (Reporter), `30` (Developer), `40` (Maintainer), and `50` (Owner). |
| `expires_at` | Date | no | Token expires at midnight UTC on that date |
```shell

View File

@ -15,6 +15,16 @@ To configure GitLab for this, see
This functionality is based on the [doorkeeper Ruby gem](https://github.com/doorkeeper-gem/doorkeeper).
## CORS preflight requests
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/364680) in GitLab 15.1.
The following endpoints support [CORS preflight requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS):
- `/oauth/revoke`
- `/oauth/token`
- `/oauth/userinfo`
## Supported OAuth 2.0 flows
GitLab supports the following authorization flows:

View File

@ -87,19 +87,25 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
Create a [project access token](../user/project/settings/project_access_tokens.md).
**NOTE:** Project Maintainers cannot create project access tokens with Owner (50) access level.
When you create a project access token, the maximum role (access level) you set depends on if you have the Owner or Maintainer role for the group. For example, the maximum
role that can be set is:
- Owner (`50`), if you have the Owner role for the project.
- Maintainer (`40`), if you have the Maintainer role on the project.
In GitLab 14.8 and earlier, project access tokens have a maximum role of Maintainer.
```plaintext
POST projects/:id/access_tokens
```
| Attribute | Type | required | Description |
|-----------|---------|----------|---------------------|
| `id` | integer or string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
| `name` | String | yes | Name of the project access token |
| `scopes` | `Array[String]` | yes | [List of scopes](../user/project/settings/project_access_tokens.md#scopes-for-a-project-access-token) |
| `access_level` | Integer | no | A valid access level. Default value is 40 (Maintainer). Other allowed values are 10 (Guest), 20 (Reporter), and 30 (Developer). |
| `expires_at` | Date | no | Token expires at midnight UTC on that date |
| Attribute | Type | required | Description |
|-----------|---------|----------|---------------------------------------------------------------------------------------------------------------------------------------|
| `id` | integer or string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
| `name` | String | yes | Name of the project access token |
| `scopes` | `Array[String]` | yes | [List of scopes](../user/project/settings/project_access_tokens.md#scopes-for-a-project-access-token) |
| `access_level` | Integer | no | Access level. Valid values are `10` (Guest), `20` (Reporter), `30` (Developer), `40` (Maintainer), and `50` (Owner). Defaults to `40`. |
| `expires_at` | Date | no | Token expires at midnight UTC on that date |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \

View File

@ -3484,7 +3484,7 @@ to the image specified in the [`image`](#image) keyword.
- `<image-name>:<tag>`
- `<image-name>@<digest>`
CI/CD variables [are supported](../variables/where_variables_can_be_used.md#gitlab-ciyml-file).
CI/CD variables [are supported](../variables/where_variables_can_be_used.md#gitlab-ciyml-file), but [not for `alias`](https://gitlab.com/gitlab-org/gitlab/-/issues/19561).
**Example of `services`**:

View File

@ -147,9 +147,12 @@ Even when creation is disabled, you can still use and revoke existing group acce
## Bot users for groups
Each time you create a group access token, a bot user is created and added to the group.
These bot users are similar to [bot users for projects](../../project/settings/project_access_tokens.md#bot-users-for-projects),
except they are added to groups instead of projects.
These bot users do not count as licensed seats.
Each time you create a group access token, a bot user is created and added to the group. These bot users are similar to
[bot users for projects](../../project/settings/project_access_tokens.md#bot-users-for-projects), except they are added
to groups instead of projects. Bot users for groups:
- Do not count as licensed seats.
- Can have a maximum role of Owner for a group. For more information, see
[Create a group access token](../../../api/group_access_tokens.md#create-a-group-access-token).
For more information, see [Bot users for projects](../../project/settings/project_access_tokens.md#bot-users-for-projects).

View File

@ -43,6 +43,8 @@ configured for personal access tokens.
## Create a project access token
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89114) in GitLab 15.1, Owners can select Owner role for project access tokens.
To create a project access token:
1. On the top bar, select **Menu > Projects** and find your project.
@ -102,8 +104,6 @@ These bot users do not count as licensed seats.
The bot users for projects have [permissions](../../permissions.md#project-members-permissions) that correspond with the
selected role and [scope](#scopes-for-a-project-access-token) of the project access token.
**Note** Project maintainers cannot select Owner role for bot users.
- The name is set to the name of the token.
- The username is set to `project_{project_id}_bot` for the first access token. For example, `project_123_bot`.
- The email is set to `project{project_id}_bot@noreply.{Gitlab.config.gitlab.host}`. For example, `project123_bot@noreply.example.com`.
@ -118,6 +118,8 @@ Bot users for projects:
- Are included in a project's member list but cannot be modified.
- Cannot be added to any other project.
- Can have a maximum role of Owner for a project. For more information, see
[Create a project access token](../../../api/project_access_tokens.md#create-a-project-access-token).
When the project access token is [revoked](#revoke-a-project-access-token):

View File

@ -8,11 +8,12 @@ module ContainerRegistry
class BaseClient
DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE = 'application/vnd.docker.distribution.manifest.v2+json'
DOCKER_DISTRIBUTION_MANIFEST_LIST_V2_TYPE = 'application/vnd.docker.distribution.manifest.list.v2+json'
OCI_DISTRIBUTION_INDEX_TYPE = 'application/vnd.oci.image.index.v1+json'
OCI_MANIFEST_V1_TYPE = 'application/vnd.oci.image.manifest.v1+json'
CONTAINER_IMAGE_V1_TYPE = 'application/vnd.docker.container.image.v1+json'
ACCEPTED_TYPES = [DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE, OCI_MANIFEST_V1_TYPE].freeze
ACCEPTED_TYPES_RAW = [DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE, OCI_MANIFEST_V1_TYPE, DOCKER_DISTRIBUTION_MANIFEST_LIST_V2_TYPE].freeze
ACCEPTED_TYPES_RAW = [DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE, OCI_MANIFEST_V1_TYPE, DOCKER_DISTRIBUTION_MANIFEST_LIST_V2_TYPE, OCI_DISTRIBUTION_INDEX_TYPE].freeze
RETRY_EXCEPTIONS = [Faraday::Request::Retry::DEFAULT_EXCEPTIONS, Faraday::ConnectionFailed].flatten.freeze
RETRY_OPTIONS = {
@ -107,6 +108,7 @@ module ContainerRegistry
conn.response :json, content_type: 'application/vnd.docker.distribution.manifest.v1+json'
conn.response :json, content_type: DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE
conn.response :json, content_type: OCI_MANIFEST_V1_TYPE
conn.response :json, content_type: OCI_DISTRIBUTION_INDEX_TYPE
end
def delete_if_exists(path)

View File

@ -1,29 +0,0 @@
# frozen_string_literal: true
module Gitlab
module Analytics
class UniqueVisits
# Returns number of unique visitors for given targets in given time frame
#
# @param [String, Array[<String>]] targets ids of targets to count visits on. Special case for :any
# @param [ActiveSupport::TimeWithZone] start_date start of time frame
# @param [ActiveSupport::TimeWithZone] end_date end of time frame
# @return [Integer] number of unique visitors
def unique_visits_for(targets:, start_date: 7.days.ago, end_date: start_date + 1.week)
events = if targets == :compliance
self.class.compliance_events
else
Array(targets)
end
Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, start_date: start_date, end_date: end_date)
end
class << self
def compliance_events
Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category('compliance')
end
end
end
end
end

View File

@ -9,10 +9,7 @@ module Gitlab
# see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54578 for discussion
class MigratePagesToZipStorage
def perform(start_id, stop_id)
::Pages::MigrateFromLegacyStorageService.new(Gitlab::AppLogger,
ignore_invalid_entries: false,
mark_projects_as_not_deployed: false)
.execute_for_batch(start_id..stop_id)
# no-op
end
end
end

View File

@ -27,7 +27,6 @@ module Gitlab
project_maximum_id
user_minimum_id
user_maximum_id
unique_visit_service
deployment_minimum_id
deployment_maximum_id
auth_providers
@ -67,13 +66,17 @@ module Gitlab
# rubocop: disable Metrics/AbcSize
# rubocop: disable CodeReuse/ActiveRecord
def system_usage_data
issues_created_manually_from_alerts = count(Issue.with_alert_management_alerts.not_authored_by(::User.alert_bot), start: minimum_id(Issue), finish: maximum_id(Issue))
issues_created_manually_from_alerts = if Gitlab.com?
FALLBACK
else
count(Issue.with_alert_management_alerts.not_authored_by(::User.alert_bot), start: minimum_id(Issue), finish: maximum_id(Issue))
end
{
counts: {
assignee_lists: count(List.assignee),
ci_builds: count(::Ci::Build),
ci_internal_pipelines: count(::Ci::Pipeline.internal),
ci_internal_pipelines: Gitlab.com? ? FALLBACK : count(::Ci::Pipeline.internal),
ci_external_pipelines: count(::Ci::Pipeline.external),
ci_pipeline_config_auto_devops: count(::Ci::Pipeline.auto_devops_source),
ci_pipeline_config_repository: count(::Ci::Pipeline.repository_source),
@ -643,16 +646,6 @@ module Gitlab
}
end
def compliance_unique_visits_data
results = ::Gitlab::Analytics::UniqueVisits.compliance_events.each_with_object({}) do |target, hash|
hash[target] = redis_usage_data { unique_visit_service.unique_visits_for(targets: target) }
end
results['compliance_unique_visits_for_any_target'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :compliance) }
results['compliance_unique_visits_for_any_target_monthly'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :compliance, **monthly_time_range) }
{ compliance_unique_visits: results }
end
def action_monthly_active_users(time_period)
date_range = { date_from: time_period[:created_at].first, date_to: time_period[:created_at].last }
@ -700,7 +693,6 @@ module Gitlab
.merge(topology_usage_data)
.merge(usage_activity_by_stage)
.merge(usage_activity_by_stage(:usage_activity_by_stage_monthly, monthly_time_range_db_params))
.merge(compliance_unique_visits_data)
.merge(redis_hll_counters)
.deep_merge(aggregated_metrics_data)
end
@ -803,12 +795,6 @@ module Gitlab
clicked_emails.is_a?(Hash) ? clicked_emails.fetch([track, series], 0) : clicked_emails
end
def unique_visit_service
strong_memoize(:unique_visit_service) do
::Gitlab::Analytics::UniqueVisits.new
end
end
def total_alert_issues
# Remove prometheus table queries once they are deprecated
# To be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/217407.

View File

@ -1008,6 +1008,9 @@ msgstr[1] ""
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
msgid "%{strong_start}%{project_name}%{strong_end} is a personal project, so you cant upgrade to a paid plan or start a free trial to lift these limits. We recommend %{move_to_group_link}moving this project to a group%{end_link} to unlock these options. You can %{manage_members_link}manage the members of this project%{end_link}, but dont forget that all unique members in your personal namespace %{strong_start}%{namespace_name}%{strong_end} count towards total seats in use."
msgstr ""
msgid "%{strong_start}%{release_count}%{strong_end} Release"
msgid_plural "%{strong_start}%{release_count}%{strong_end} Releases"
msgstr[0] ""
@ -11364,15 +11367,15 @@ msgstr ""
msgid "DastConfig|Customize DAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{docsLinkStart}GitLab DAST documentation%{docsLinkEnd}."
msgstr ""
msgid "DastConfig|DAST Settings"
msgid "DastConfig|DAST CI/CD configuration"
msgstr ""
msgid "DastConfig|Enable DAST to automatically test for vulnerabilities in your project's running application, website, or API, in the CI/CD pipeline. Configuration changes must be applied to your .gitlab-ci.yml file to take effect. For details of all configuration options, see the %{linkStart}GitLab DAST documentation%{linkEnd}."
msgstr ""
msgid "DastConfig|Generate code snippet"
msgstr ""
msgid "DastConfig|Scan Configuration"
msgstr ""
msgid "DastProfiles|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
msgstr ""
@ -25527,9 +25530,6 @@ msgstr ""
msgid "New! Suggest changes directly"
msgstr ""
msgid "New..."
msgstr ""
msgid "Newest first"
msgstr ""
@ -44325,6 +44325,9 @@ msgstr ""
msgid "Your profile"
msgstr ""
msgid "Your project has limited quotas and features"
msgstr ""
msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
msgstr ""

View File

@ -2,11 +2,7 @@
module QA
RSpec.describe 'Create' do
describe 'Merge request creation from fork', quarantine: {
only: :production,
issue: "https://gitlab.com/gitlab-org/gitlab/-/issues/343801",
type: :investigating
} do
describe 'Merge request creation from fork' do
let(:merge_request) do
Resource::MergeRequestFromFork.fabricate_via_browser_ui! do |merge_request|
merge_request.fork_branch = 'feature-branch'

View File

@ -41,7 +41,7 @@ RSpec.describe 'top nav responsive', :js do
end
it 'has new dropdown', :aggregate_failures do
click_button('New...')
click_button('Create new')
expect(page).to have_link('New project', href: new_project_path)
expect(page).to have_link('New group', href: new_group_path)

View File

@ -15,10 +15,10 @@ RSpec.describe 'top nav tooltips', :js do
page.find(btn).hover
expect(page).to have_content('New...')
expect(page).to have_content('Create new')
page.find(btn).click
expect(page).not_to have_content('New...')
expect(page).not_to have_content('Create new')
end
end

View File

@ -55,7 +55,7 @@ RSpec.describe Nav::NewDropdownHelper do
end
it 'has title' do
expect(subject[:title]).to eq('New...')
expect(subject[:title]).to eq('Create new')
end
context 'when current_user is nil (anonymous)' do

View File

@ -1,43 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::MigratePagesToZipStorage do
let(:namespace) { create(:group) } # rubocop: disable RSpec/FactoriesInMigrationSpecs
let(:migration) { described_class.new }
describe '#perform' do
context 'when there is project to migrate' do
let!(:project) { create_project('project') }
after do
FileUtils.rm_rf(project.pages_path)
end
it 'migrates project to zip storage' do
expect_next_instance_of(::Pages::MigrateFromLegacyStorageService,
anything,
ignore_invalid_entries: false,
mark_projects_as_not_deployed: false) do |service|
expect(service).to receive(:execute_for_batch).with(project.id..project.id).and_call_original
end
migration.perform(project.id, project.id)
expect(project.reload.pages_metadatum.pages_deployment.file.filename).to eq("_migrated.zip")
end
end
end
def create_project(path)
project = create(:project) # rubocop: disable RSpec/FactoriesInMigrationSpecs
project.mark_pages_as_deployed
FileUtils.mkdir_p File.join(project.pages_path, "public")
File.open(File.join(project.pages_path, "public/index.html"), "w") do |f|
f.write("Hello!")
end
project
end
end

View File

@ -84,7 +84,6 @@ RSpec.describe Gitlab::Usage::Metrics::NameSuggestion do
context 'for redis metrics' do
it_behaves_like 'name suggestion' do
# corresponding metric is collected with redis_usage_data { unique_visit_service.unique_visits_for(targets: :analytics) }
let(:operation) { :redis }
let(:column) { nil }
let(:relation) { nil }

View File

@ -77,8 +77,7 @@ RSpec.describe Gitlab::Usage::Metrics::NamesSuggestions::Generator do
context 'for redis metrics' do
it_behaves_like 'name suggestion' do
# corresponding metric is collected with redis_usage_data { unique_visit_service.unique_visits_for(targets: :compliance) }
let(:key_path) { 'compliance_unique_visits.compliance_unique_visits_for_any_target' }
let(:key_path) { 'usage_activity_by_stage_monthly.create.merge_requests_users' }
let(:name_suggestion) { /<please fill metric name, suggested format is: {subject}_{verb}{ing|ed}_{object} eg: users_creating_epics or merge_requests_viewed_in_single_file_mode>/ }
end
end

View File

@ -1204,36 +1204,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
end
describe '.compliance_unique_visits_data' do
subject { described_class.compliance_unique_visits_data }
before do
allow_next_instance_of(::Gitlab::Analytics::UniqueVisits) do |instance|
::Gitlab::Analytics::UniqueVisits.compliance_events.each do |target|
allow(instance).to receive(:unique_visits_for).with(targets: target).and_return(123)
end
allow(instance).to receive(:unique_visits_for).with(targets: :compliance).and_return(543)
allow(instance).to receive(:unique_visits_for).with(targets: :compliance, start_date: 4.weeks.ago.to_date, end_date: Date.current).and_return(987)
end
end
it 'returns the number of unique visits to pages with compliance features' do
expect(subject).to eq({
compliance_unique_visits: {
'g_compliance_dashboard' => 123,
'g_compliance_audit_events' => 123,
'i_compliance_credential_inventory' => 123,
'i_compliance_audit_events' => 123,
'a_compliance_audit_events_api' => 123,
'compliance_unique_visits_for_any_target' => 543,
'compliance_unique_visits_for_any_target_monthly' => 987
}
})
end
end
describe 'redis_hll_counters' do
subject { described_class.redis_hll_counters }
@ -1423,4 +1393,20 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
end
end
context 'on Gitlab.com' do
before do
allow(Gitlab).to receive(:com?).and_return(true)
end
describe '.system_usage_data' do
subject { described_class.system_usage_data }
it 'returns fallback value for disabled metrics' do
expect(subject[:counts][:ci_internal_pipelines]).to eq(Gitlab::Utils::UsageData::FALLBACK)
expect(subject[:counts][:issues_created_gitlab_alerts]).to eq(Gitlab::Utils::UsageData::FALLBACK)
expect(subject[:counts][:issues_created_manually_from_alerts]).to eq(Gitlab::Utils::UsageData::FALLBACK)
end
end
end
end

View File

@ -1,46 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe ScheduleMigratePagesToZipStorage, :sidekiq_might_not_need_inline, schema: 20210301200959 do
let(:migration_class) { described_class::MIGRATION }
let(:migration_name) { migration_class.to_s.demodulize }
let(:namespaces_table) { table(:namespaces) }
let(:projects_table) { table(:projects) }
let(:metadata_table) { table(:project_pages_metadata) }
let(:deployments_table) { table(:pages_deployments) }
let(:namespace) { namespaces_table.create!(path: "group", name: "group") }
def create_project_metadata(path, deployed, with_deployment)
project = projects_table.create!(path: path, namespace_id: namespace.id)
deployment_id = nil
if with_deployment
deployment_id = deployments_table.create!(project_id: project.id, file_store: 1, file: '1', file_count: 1, file_sha256: '123', size: 1).id
end
metadata_table.create!(project_id: project.id, deployed: deployed, pages_deployment_id: deployment_id)
end
it 'correctly schedules background migrations' do
Sidekiq::Testing.fake! do
freeze_time do
create_project_metadata("not-deployed-project", false, false)
first_id = create_project_metadata("project1", true, false).id
last_id = create_project_metadata("project2", true, false).id
create_project_metadata("project-with-deployment", true, true)
migrate!
expect(migration_name).to be_scheduled_delayed_migration(5.minutes, first_id, last_id)
expect(BackgroundMigrationWorker.jobs.size).to eq(1)
end
end
end
end

View File

@ -294,31 +294,28 @@ RSpec.describe Ci::Build do
end
end
describe '.with_reports' do
subject { described_class.with_reports(Ci::JobArtifact.test_reports) }
describe '.with_artifacts' do
subject(:builds) { described_class.with_artifacts(artifact_scope) }
context 'when build has a test report' do
let!(:build) { create(:ci_build, :success, :test_reports) }
let(:artifact_scope) { Ci::JobArtifact.where(file_type: 'archive') }
it 'selects the build' do
is_expected.to eq([build])
end
let!(:build_1) { create(:ci_build, :artifacts) }
let!(:build_2) { create(:ci_build, :codequality_reports) }
let!(:build_3) { create(:ci_build, :test_reports) }
let!(:build_4) { create(:ci_build, :artifacts) }
it 'returns artifacts matching the given scope' do
expect(builds).to contain_exactly(build_1, build_4)
end
context 'when build does not have test reports' do
let!(:build) { create(:ci_build, :success, :trace_artifact) }
it 'does not select the build' do
is_expected.to be_empty
context 'when there are multiple builds containing artifacts' do
before do
create_list(:ci_build, 5, :success, :test_reports)
end
end
context 'when there are multiple builds with test reports' do
let!(:builds) { create_list(:ci_build, 5, :success, :test_reports) }
it 'does not execute a query for selecting job artifact one by one' do
recorded = ActiveRecord::QueryRecorder.new do
subject.each do |build|
builds.each do |build|
build.job_artifacts.map { |a| a.file.exists? }
end
end

View File

@ -33,10 +33,10 @@ RSpec.describe Ci::JobArtifact do
end
end
describe '.with_reports' do
describe '.all_reports' do
let!(:artifact) { create(:ci_job_artifact, :archive) }
subject { described_class.with_reports }
subject { described_class.all_reports }
it { is_expected.to be_empty }

View File

@ -0,0 +1,76 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Oauth::AuthorizationsController do
let_it_be(:user) { create(:user) }
let_it_be(:application) { create(:oauth_application, redirect_uri: 'custom://test') }
let_it_be(:oauth_authorization_path) do
Gitlab::Routing.url_helpers.oauth_authorization_url(
client_id: application.uid,
response_type: 'code',
scope: application.scopes,
redirect_uri: application.redirect_uri,
state: SecureRandom.hex
)
end
before do
sign_in(user)
end
describe 'GET #new' do
context 'when application redirect URI has a custom scheme' do
context 'when CSP is disabled' do
before do
allow_next_instance_of(ActionDispatch::Request) do |instance|
allow(instance).to receive(:content_security_policy).and_return(nil)
end
end
it 'does not add a CSP' do
get oauth_authorization_path
expect(response.headers['Content-Security-Policy']).to be_nil
end
end
context 'when CSP contains form-action' do
before do
csp = ActionDispatch::ContentSecurityPolicy.new do |p|
p.form_action "'self'"
end
allow_next_instance_of(ActionDispatch::Request) do |instance|
allow(instance).to receive(:content_security_policy).and_return(csp)
end
end
it 'adds custom scheme to CSP form-action' do
get oauth_authorization_path
expect(response.headers['Content-Security-Policy']).to include("form-action 'self' custom:")
end
end
context 'when CSP does not contain form-action' do
before do
csp = ActionDispatch::ContentSecurityPolicy.new do |p|
p.script_src :self, 'https://some-cdn.test'
p.style_src :self, 'https://some-cdn.test'
end
allow_next_instance_of(ActionDispatch::Request) do |instance|
allow(instance).to receive(:content_security_policy).and_return(csp)
end
end
it 'does not add form-action to the CSP' do
get oauth_authorization_path
expect(response.headers['Content-Security-Policy']).not_to include('form-action')
end
end
end
end
end