Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-07-10 18:28:54 +00:00
parent b7b4bb751c
commit b1016dffb4
68 changed files with 1416 additions and 273 deletions

View File

@ -2,6 +2,25 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 17.1.2 (2024-07-09)
### Fixed (2 changes)
- [Update dependency slack-messenger to v2.3.5](gitlab-org/security/gitlab@e21a4599ab21cc6f6b89ca432d9557ed72169c85)
- [Fix MailRoom not loading in Omnibus](gitlab-org/security/gitlab@5547c1164c494705bf29595062124ff8cb266cb3)
### Security (9 changes)
- [Disallow serving Pages over disabled custom domains with deployments](gitlab-org/security/gitlab@176442d616a111667481f22186560925d1175c67) ([merge request](gitlab-org/security/gitlab!4245))
- [Check npm package name, version and scripts coherence](gitlab-org/security/gitlab@917d805ce57e5d0439b4a4c757967d494014a97d) ([merge request](gitlab-org/security/gitlab!4212))
- [Check for create_deploy_token policy before creating deploy token](gitlab-org/security/gitlab@8ae4e9b0b25bec92561698da3c7d0495d6ba61bc) ([merge request](gitlab-org/security/gitlab!4209))
- [Check if user has ban_group_member access before banning in namespace](gitlab-org/security/gitlab@eefb608987d64b9cf58411b8520f260d1fb9b1c3) ([merge request](gitlab-org/security/gitlab!4091))
- [Prevent privilege escalation via custom role](gitlab-org/security/gitlab@a618e86dc4585b0fef049f75f13acf0eec00656d) ([merge request](gitlab-org/security/gitlab!4199))
- [Prevent using quick actions for some bot users](gitlab-org/security/gitlab@5789cc333d04d76ffb4c79239e71be1910f12229) ([merge request](gitlab-org/security/gitlab!4231))
- [Disable raw HTML for quick action pipeline](gitlab-org/security/gitlab@7db9b002b803cb6b53a3e6ce3f8d9b15107e7464) ([merge request](gitlab-org/security/gitlab!4235))
- [Disable quick actions unless description changed](gitlab-org/security/gitlab@a1800c591b38df0e2d143df3ee56f76b4f3a914f) ([merge request](gitlab-org/security/gitlab!4234))
- [Remove comment support from shrug and tableflip](gitlab-org/security/gitlab@fb6bcef1935dc3a7dd60def448a652769c86ee62) ([merge request](gitlab-org/security/gitlab!4229))
## 17.1.1 (2024-06-25)
### Fixed (1 change)
@ -1125,6 +1144,24 @@ entry.
- [Update Web IDE dependency to receive duo fixes](gitlab-org/gitlab@47323c05565dd32ea4de9f999adbd9f7aa8748e3) ([merge request](gitlab-org/gitlab!154064))
## 17.0.4 (2024-07-09)
### Fixed (1 change)
- [Update dependency slack-messenger to v2.3.5](gitlab-org/security/gitlab@8800f576925de4fcf00d46f707a70e1e81e5f00a)
### Security (9 changes)
- [Disallow serving Pages over disabled custom domains with deployments](gitlab-org/security/gitlab@760d6115e963e744ee55230be45e9fc3c138a73d) ([merge request](gitlab-org/security/gitlab!4248))
- [Check npm package name, version and scripts coherence](gitlab-org/security/gitlab@f3b322c5e20036e380ac15b3b2614d9bcc800e75) ([merge request](gitlab-org/security/gitlab!4158))
- [Check for create_deploy_token policy before creating deploy token](gitlab-org/security/gitlab@87ab0448c48a0ac45540986f4f7429cbc0db3e04) ([merge request](gitlab-org/security/gitlab!4168))
- [Check if user has ban_group_member access before banning in namespace](gitlab-org/security/gitlab@1b69ccb4a7e7e16372a926d7e2954aec76cdc0fd) ([merge request](gitlab-org/security/gitlab!4087))
- [Prevent privilege escalation via custom role](gitlab-org/security/gitlab@288e1493a3c16689993d7cbbd7f60cd9bdeffcc0) ([merge request](gitlab-org/security/gitlab!4198))
- [Prevent using quick actions for some bot users](gitlab-org/security/gitlab@5b8aef69fc74e5aba42d65591902a151a1654316) ([merge request](gitlab-org/security/gitlab!4232))
- [Disable raw HTML for quick action pipeline](gitlab-org/security/gitlab@0ca2b123f1f627e68b73a1699fbefbb4a70c28d1) ([merge request](gitlab-org/security/gitlab!4236))
- [Disable quick actions unless description changed](gitlab-org/security/gitlab@9e5397fbd82497083cd69f526a13caea1b5efd21) ([merge request](gitlab-org/security/gitlab!4239))
- [Remove comment support from shrug and tableflip](gitlab-org/security/gitlab@e378c24c4a1a8dd323bd157bce29b21cca1e0701) ([merge request](gitlab-org/security/gitlab!4228))
## 17.0.3 (2024-06-25)
### Fixed (5 changes)
@ -2051,6 +2088,21 @@ entry.
- [Migrate self-managed custom roles to the instance-level roles](gitlab-org/gitlab@46ab664a1877f8b761c2b25e13e01561d56cf6fd) ([merge request](gitlab-org/gitlab!147829))
- [Feature cleanup flag wiki_content_background_job](gitlab-org/gitlab@c39a37db4a6112456052c11bf5fd1afa9c23bd6d) by @ivantedja ([merge request](gitlab-org/gitlab!148820))
## 16.11.6 (2024-07-09)
### Fixed (1 change)
- [Update dependency slack-messenger to v2.3.5](gitlab-org/security/gitlab@4e78461cef64c7423d793de22deffbae7088e7d6)
### Security (6 changes)
- [Disallow serving Pages over disabled custom domains with deployments](gitlab-org/security/gitlab@ff23e03cab7495107b1342b4fa175db63a4acd61) ([merge request](gitlab-org/security/gitlab!4247))
- [Check if user has ban_group_member access before banning in namespace](gitlab-org/security/gitlab@cadb2dba7f5fe825fab7fe761259e7c1721bebfe) ([merge request](gitlab-org/security/gitlab!4090))
- [Prevent using quick actions for some bot users](gitlab-org/security/gitlab@951a656e6d530ba7692b03506b7c340bc5ac2788) ([merge request](gitlab-org/security/gitlab!4233))
- [Disable raw HTML for quick action pipeline](gitlab-org/security/gitlab@1a7f336059af3223b4886e79060b8dc8a17f5482) ([merge request](gitlab-org/security/gitlab!4237))
- [Disable quick actions unless description changed](gitlab-org/security/gitlab@267f4cf51303f70d5a834a3358fe62b6e981a873) ([merge request](gitlab-org/security/gitlab!4240))
- [Remove comment support from shrug and tableflip](gitlab-org/security/gitlab@579a180538609ccad2d3930218a5410cb33d3920) ([merge request](gitlab-org/security/gitlab!4230))
## 16.11.5 (2024-06-25)
### Fixed (2 changes)

View File

@ -388,6 +388,8 @@ gem 'gettext', '~> 3.4', '>= 3.4.9',
gem 'batch-loader', '~> 2.0.5' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'tty-prompt', '~> 0.23', require: false, feature_category: :shared
# Perf bar
gem 'peek', '~> 1.1' # rubocop:todo Gemfile/MissingFeatureCategory

View File

@ -2262,6 +2262,7 @@ DEPENDENCIES
timfel-krb5-auth (~> 0.8)
toml-rb (~> 2.2.0)
truncato (~> 0.7.12)
tty-prompt (~> 0.23)
typhoeus (~> 1.4.0)
undercover (~> 0.4.4)
unleash (~> 3.2.2)

View File

@ -185,7 +185,10 @@ export default {
this.submitForm();
},
setPasswordComplexity({ name, value }) {
this.$set(this.form, name, value);
this.form = {
...this.form,
[name]: value,
};
},
submitForm() {
this.$refs.form.submit();

View File

@ -15,6 +15,10 @@ class Packages::Npm::Metadatum < ApplicationRecord
scope :package_id_in, ->(package_ids) { where(package_id: package_ids) }
def package_json_scripts
package_json.try(:[], 'scripts')
end
private
def ensure_npm_package_type

View File

@ -26,6 +26,23 @@ class GlobalPolicy < BasePolicy
condition(:service_account, scope: :user) { @user&.service_account? }
condition(:bot, scope: :user) { @user&.bot? }
# By default bots should not be allowed to use quick actions as they have too many permissions and it can lead to
# surprises. We should scope down this allowlist over time as we confirm if these bots actually need to use quick
# actions.
condition(:bot_with_quick_actions_permitted) do
@user.alert_bot? ||
@user.project_bot? ||
@user.support_bot? ||
@user.admin_bot? ||
@user.service_account?
end
rule { bot & ~bot_with_quick_actions_permitted }.policy do
prevent :use_quick_actions
end
rule { anonymous }.policy do
prevent :log_in
prevent :receive_notifications

View File

@ -60,18 +60,16 @@ module WorkItems
def interpret_quick_actions!(work_item, widget_params, attributes = {})
return unless work_item.has_widget?(:description)
description_param = widget_params[::WorkItems::Widgets::Description.api_symbol]
return unless description_param
widget_description_param = widget_params[::WorkItems::Widgets::Description.api_symbol]
return unless widget_description_param
original_description = description_param.fetch(:description, work_item.description)
merge_quick_actions_into_params!(work_item, params: widget_description_param)
description, command_params = QuickActions::InterpretService
.new(container: work_item.resource_parent, current_user: current_user)
.execute(original_description, work_item)
# cleanup `description` param so that it is not passed into common params after transform_quick_action_params
quick_action_params = widget_description_param.dup
quick_action_params.delete(:description)
description_param[:description] = description if description && description != original_description
parsed_params = work_item.transform_quick_action_params(command_params)
parsed_params = work_item.transform_quick_action_params(quick_action_params)
widget_params.merge!(parsed_params[:widgets])
attributes.merge!(parsed_params[:common])

View File

@ -209,28 +209,50 @@ class IssuableBaseService < ::BaseContainerService
end
def handle_quick_actions(issuable)
merge_quick_actions_into_params!(issuable)
merge_quick_actions_into_params!(issuable, params: params)
end
def merge_quick_actions_into_params!(issuable, only: nil)
original_description = params.fetch(:description, issuable.description)
# Notes: When the description has been edited, then we need to sanitize and compare with
# the original description, removing any extra quick actions.
# If the description has not been edited, then just remove any quick actions
# in the current description.
def merge_quick_actions_into_params!(issuable, params:, only: nil)
interpret_params = quick_action_options
unedited_description = issuable.description
edited_description = params.fetch(:description, issuable.description)
description, command_params = QuickActions::InterpretService.new(
container: container,
current_user: current_user,
params: quick_action_options
).execute(original_description, issuable, only: only)
target_text = issuable.new_record? || params[:description] ? edited_description : unedited_description
# only set the original_text if we're editing the issuable
original_text = params[:description] && !issuable.new_record? ? unedited_description : nil
sanitized_description, sanitized_command_params = interpret_quick_actions(target_text, issuable, params: interpret_params, only: only, original_text: original_text)
unless issuable.new_record? || params[:description]
edited_description = unedited_description
sanitized_command_params = nil
end
# Avoid a description already set on an issuable to be overwritten by a nil
params[:description] = description if description && description != original_description
params[:description] = sanitized_description if sanitized_description && sanitized_description != edited_description
params.merge!(command_params)
params.merge!(sanitized_command_params) if sanitized_command_params
end
def quick_action_options
{}
end
def interpret_quick_actions(new_text, issuable, params:, only:, original_text: nil)
sanitized_new_text, new_command_params = QuickActions::InterpretService.new(
container: container,
current_user: current_user,
params: params
).execute_with_original_text(new_text, issuable, only: only, original_text: original_text)
[sanitized_new_text, new_command_params]
end
def create(issuable, skip_system_notes: false)
initialize_callbacks!(issuable)

View File

@ -9,7 +9,7 @@ module MergeRequests
self.merge_request = MergeRequest.new
# TODO: this should handle all quick actions that don't have side effects
# https://gitlab.com/gitlab-org/gitlab-foss/issues/53658
merge_quick_actions_into_params!(merge_request, only: [:target_branch])
merge_quick_actions_into_params!(merge_request, params: params, only: [:target_branch])
# Assign the projects first so we can use policies for `filter_params`
merge_request.author = current_user

View File

@ -147,6 +147,7 @@ module MergeRequests
draft: push_options[:draft],
target_branch: push_options[:target],
force_remove_source_branch: push_options[:remove_source_branch],
squash: push_options[:squash],
label: push_options[:label],
unlabel: push_options[:unlabel],
assign: push_options[:assign],

View File

@ -40,7 +40,10 @@ module Notes
params: options
)
interpret_service.execute(note.note, note.noteable)
# NOTE: old_note would be nil if the note hasn't changed or it is a new record
old_note, _ = note.note_change
interpret_service.execute_with_original_text(note.note, note.noteable, original_text: old_note)
end
# Applies updates extracted to note#noteable

View File

@ -0,0 +1,94 @@
# frozen_string_literal: true
module Packages
module Npm
class CheckManifestCoherenceService
MismatchError = Class.new(StandardError)
delegate :npm_metadatum, to: :package, private: true
delegate :package_json_scripts, to: :npm_metadatum, private: true, allow_nil: true
def initialize(package, package_json_entry)
@package = package
@package_json_entry = package_json_entry
@handler = SajHandler.new
end
def execute
extract_manifest_data
raise MismatchError, 'Package manifest is not coherent' unless coherent?
ServiceResponse.success
end
private
attr_reader :package, :package_json_entry, :handler
def extract_manifest_data
::Oj.saj_parse(handler, package_json_entry)
rescue SajHandler::ParsingDoneError
# no-op
# this simply signals that the handler has been stopped
# and that's ok.
end
def coherent?
handler.name == package.name &&
handler.version == package.version &&
handler.scripts == (package_json_scripts || {})
end
class SajHandler < ::Oj::Saj
ParsingDoneError = Class.new(StandardError)
attr_reader :name, :version, :scripts
def initialize
@in_scripts_block = false
@scripts_processed = false
@scripts = {}
@name = nil
@version = nil
end
def hash_start(key)
return unless key == 'scripts'
self.in_scripts_block = true
end
def hash_end(key)
return unless key == 'scripts'
self.in_scripts_block = false
self.scripts_processed = true
raise ParsingDoneError if complete?
end
def add_value(value, key)
if in_scripts_block
scripts[key] = value
elsif key == 'name'
self.name = value
elsif key == 'version'
self.version = value
end
raise ParsingDoneError if complete?
end
private
attr_writer :name, :version
attr_accessor :in_scripts_block, :scripts_processed
def complete?
scripts_processed && name && version
end
end
end
end
end

View File

@ -19,6 +19,8 @@ module Packages
with_package_json_entry do |entry|
raise ExtractionError, 'package.json not found' unless entry
raise ExtractionError, 'package.json file too large' if entry.size > MAX_FILE_SIZE
::Packages::Npm::CheckManifestCoherenceService.new(package, entry).execute
end
package.default!

View File

@ -32,6 +32,9 @@ module QuickActions
end.compact
end
# IMPORTANT: unsafe! Use `execute_with_original_text` instead as it handles cleanup of any residual quick actions
# left in the original description.
#
# Takes a text and interprets the commands that are extracted from it.
# Returns the content without commands, a hash of changes to be applied to a record
# and a string containing the execution_message to show to the user.
@ -48,6 +51,26 @@ module QuickActions
[content, @updates, execution_messages_for(commands), command_names(commands)]
end
# Similar to `execute` except also tries to extract any quick actions from original_text,
# and if found removes them from the main list of quick actions.
def execute_with_original_text(new_text, quick_action_target, only: nil, original_text: nil)
sanitized_new_text, new_command_params, execution_messages, command_names = execute(
new_text, quick_action_target, only: only
)
if original_text
_, original_command_params = self.class.new(
container: container,
current_user: current_user,
params: params
).execute(original_text, quick_action_target, only: only)
new_command_params = (new_command_params.to_a - original_command_params.to_a).to_h if original_command_params
end
[sanitized_new_text, new_command_params, execution_messages, command_names]
end
# Takes a text and interprets the commands that are extracted from it.
# Returns the content without commands, and array of changes explained.
# `keep_actions: true` will keep the quick actions in the content.

View File

@ -15,7 +15,8 @@ module Packages
::Packages::Nuget::UpdatePackageFromMetadataService::ZipError,
::Packages::Rubygems::ProcessGemService::ExtractionError,
::Packages::Rubygems::ProcessGemService::InvalidMetadataError,
::Packages::Npm::ProcessPackageFileService::ExtractionError
::Packages::Npm::ProcessPackageFileService::ExtractionError,
::Packages::Npm::CheckManifestCoherenceService::MismatchError
].freeze
def process_package_file_error(package_file:, exception:, extra_log_payload: {})

View File

@ -355,3 +355,18 @@ these steps:
- `deflate` is the default encoding type for PlantUML. To use a different encoding type, PlantUML integration
[requires a header prefix in the URL](https://plantuml.com/text-encoding)
to distinguish different encoding types.
## Troubleshooting PlantUML configuration
### Rendered diagram URL remains the same after update
Rendered diagrams are cached. To see the updates, try these steps:
- If the diagram is in a Markdown file, make a small change to the Markdown file, and commit it. This triggers a re-render.
- [Clear your GitLab cache](../raketasks/maintenance.md#clear-redis-cache).
If you're still not seeing the updated URL, check the following:
- Ensure the PlantUML server is accessible from your GitLab instance.
- Verify that the PlantUML integration is enabled in your GitLab settings.
- Check the GitLab logs for errors related to PlantUML rendering.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View File

@ -26,7 +26,7 @@ To access the visibility and access control options:
## Define which roles can create projects
Instance-level protections for project creation define which roles can
You can add project creation protections to your instance. These protections define which roles can
[add projects to a group](../../user/group/index.md#specify-who-can-add-projects-to-a-group)
on the instance. To alter which roles have permission to create projects:
@ -62,7 +62,7 @@ To restrict project deletion to only administrators:
1. Expand **Visibility and access controls**.
1. Scroll to:
- (GitLab 15.1 and later) **Allowed to delete projects**, and select **Administrators**.
- (GitLab 15.0 and earlier) **Default project deletion protection** and select **Only admins can delete project**.
- (GitLab 15.0 and earlier) **Default project deletion protection**, and select **Only admins can delete project**.
1. Select **Save changes**.
## Deletion protection
@ -77,21 +77,21 @@ DETAILS:
> - [Removed option to delete immediately](https://gitlab.com/gitlab-org/gitlab/-/issues/389557) in GitLab 15.11 [with a flag](../feature_flags.md) named `always_perform_delayed_deletion`. Disabled by default.
> - Enabled delayed deletion by default and removed the option to delete immediately [on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/393622) and [on self-managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119606) in GitLab 16.0.
Instance-level protection against accidental deletion of groups and projects.
These protections help guard against accidental deletion of groups and projects on your instance.
### Retention period
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/352960) in GitLab 15.1.
Groups and projects remain restorable during the retention period you define. By default,
this is 7 days, but you can change it. If you set the retention period to `0`, GitLab
this is 7 days, but you can change it. If you set the retention period to `0` days, GitLab
removes deleted groups and projects immediately. You can't restore them.
In GitLab 15.1 and later, the retention period must be between `1` and `90`.
If the retention period was `0` before the 15.1 update, the next time you change
In GitLab 15.1 and later, the retention period must be between `1` and `90` days.
If, before the 15.1 update, you set the retention period to `0` days, the next time you change
any application setting, GitLab:
- Changes the retention period to `1`.
- Changes the retention period to `1` day.
- Disables deletion protection.
### Delayed project deletion
@ -102,23 +102,35 @@ any application setting, GitLab:
Prerequisites:
- You must be an administrator.
- You must enable delayed project deletion for groups before you can enable it for projects.
Deletion protection is not available for projects only.
- When disabled, GitLab 15.1 and later enforces this delayed-deletion setting, and you can't override it.
To configure delayed project deletion:
::Tabs
:::TabTitle GitLab 16.0 and later
1. On the left sidebar, at the bottom, select **Admin Area**.
1. Select **Settings > General**.
1. Expand **Visibility and access controls**.
1. Scroll to **Deletion protection** and set the retention period to a value between `1` and `90` days.
1. Select **Save changes**.
:::TabTitle GitLab 15.11 and earlier
1. On the left sidebar, at the bottom, select **Admin Area**.
1. Select **Settings > General**.
1. Expand **Visibility and access controls**.
1. Scroll to:
- In GitLab 16.0 and later: **Deletion protection** and set the retention period to a value between `1` and `90`.
- In GitLab 15.11 with `always_perform_delayed_deletion` feature flag enabled: **Deletion protection** and set the retention period to a value between `1` and `90`.
- In GitLab 15.11 with `always_perform_delayed_deletion` feature flag enabled: **Deletion protection** and set the retention period to a value between `1` and `90` days.
- In GitLab 15.1 to 15.10: **Deletion protection** and select **Keep deleted groups and projects**, then set the retention period.
- In GitLab 15.0 and earlier: **Default delayed project protection** and select **Enable delayed project deletion by
default for newly-created groups**, then set the retention period.
1. Select **Save changes**.
Deletion protection is not available for projects only (without being also being enabled for groups).
GitLab 15.1 and later enforces this setting on groups when disabled. You can't override this setting.
::EndTabs
### Delayed group deletion
@ -127,11 +139,16 @@ GitLab 15.1 and later enforces this setting on groups when disabled. You can't o
Groups remain restorable if the retention period is `1` or more days.
In GitLab 15.1 and later, enable delayed group deletion by setting **Deletion projection** to **Keep deleted**.
In GitLab 15.11 and later with the `always_perform_delayed_deletion` feature flag enabled, or in GitLab 16.0 and later:
In GitLab 16.0 and later, the **Keep deleted** option is removed, and delayed group deletion is the default.
- The **Keep deleted** option is removed.
- Delayed group deletion is the default.
To enable delayed group deletion in GitLab 15:
1. GitLab 15.11 only: enable the `always_perform_delayed_deletion` feature flag.
1. On the left sidebar, at the bottom, select **Admin Area**.
1. Select **Settings > General**.
1. Expand **Visibility and access controls**.
1. For **Deletion projection**, select **Keep deleted**.
1. Select **Save changes**.
### Override defaults and delete immediately
@ -153,15 +170,12 @@ Prerequisites:
1. Select **Settings > General**.
1. Expand **Visibility and access controls**.
1. Select the desired default project visibility:
- **Private** - Project access must be granted explicitly to each user. If this
project is part of a group, access is granted to members of the group.
- **Internal** - The project can be accessed by any authenticated user except external users.
- **Public** - The project can be accessed without any authentication.
- **Private** - Grant project access explicitly to each user. If this
project is part of a group, grants access to members of the group.
- **Internal** - Any authenticated user, except external users, can access the project.
- **Public** - Any user can access the project without any authentication.
1. Select **Save changes**.
For more details on project visibility, see
[Project visibility](../../user/public_access.md).
## Configure snippet visibility defaults
To set the default visibility levels for new [snippets](../../user/snippets.md):
@ -173,12 +187,14 @@ Prerequisites:
1. On the left sidebar, at the bottom, select **Admin Area**.
1. Select **Settings > General**.
1. Expand **Visibility and access controls**.
1. Select the desired default snippet visibility.
1. For **Default snippet visibility**, select your desired visibility level:
- **Private**.
- **Internal**. This setting is disabled for new projects, groups, and snippets on GitLab.com.
Existing snippets using the `Internal` visibility setting keep this setting. To learn more
about this change, see [issue 12388](https://gitlab.com/gitlab-org/gitlab/-/issues/12388).
- **Public**.
1. Select **Save changes**.
For more details on snippet visibility, read
[Snippet visibility](../../user/snippets.md).
## Configure group visibility defaults
To set the default visibility levels for new groups:
@ -190,9 +206,9 @@ Prerequisites:
1. On the left sidebar, at the bottom, select **Admin Area**.
1. Select **Settings > General**.
1. Expand **Visibility and access controls**.
1. Select the desired default group visibility:
1. For **Default group visibility**, select your desired visibility level:
- **Private** - Only members can view the group and its projects.
- **Internal** - Any authenticated user (except external users) can view the group and any internal projects.
- **Internal** - Any authenticated user, except external users, can view the group and any internal projects.
- **Public** - Authentication is not required to view the group and any public projects.
1. Select **Save changes**.
@ -218,7 +234,7 @@ Prerequisites:
1. On the left sidebar, at the bottom, select **Admin Area**.
1. Select **Settings > General**.
1. Expand **Visibility and access controls**.
1. In the **Restricted visibility levels** section, select the desired visibility levels to restrict.
1. For **Restricted visibility levels**, select the desired visibility levels to restrict.
- If you restrict the **Public** level:
- Only administrators can create public groups, projects, and snippets.
- User profiles are visible to only authenticated users through the Web interface.
@ -241,7 +257,13 @@ communicate with GitLab. Disabling an access protocol does not block port access
server itself. The ports used for the protocol, SSH or HTTP(S), are still accessible.
The GitLab restrictions apply at the application level.
To specify the enabled Git access protocols:
GitLab allows Git actions only for the protocols you select:
- If you enable both SSH and HTTP(S), users can choose either protocol.
- If you enable only one protocol, project pages show only the allowed protocol's
URL, with no option to change it.
To specify the enabled Git access protocols for all projects on your instance:
Prerequisites:
@ -250,24 +272,12 @@ Prerequisites:
1. On the left sidebar, at the bottom, select **Admin Area**.
1. Select **Settings > General**.
1. Expand **Visibility and access controls**.
1. Select the desired Git access protocols:
- Both SSH and HTTP(S)
- Only SSH
- Only HTTP(S)
1. For **Enabled Git access protocols**, select your desired protocols:
- Both SSH and HTTP(S).
- Only SSH.
- Only HTTP(S).
1. Select **Save changes**.
If you enable both SSH and HTTP(S), users can choose either protocol.
If you enable only one protocol:
- The project page shows only the allowed protocol's URL, with no option to
change it.
- GitLab shows a tooltip when you hover over the protocol for the URL, if user action
(such as adding a SSH key or setting a password) is required:
![Project URL with SSH only access](../settings/img/restricted_url.png)
GitLab only allows Git actions for the protocols you select.
WARNING:
GitLab [allows the HTTP(S) protocol](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18021)
for Git clone or fetch requests performed [with GitLab CI/CD job tokens](../../ci/jobs/ci_job_token.md).
@ -276,7 +286,7 @@ This happens even if you select **Only SSH**, because GitLab Runner and CI/CD jo
## Customize Git clone URL for HTTP(S)
You can customize project Git clone URLs for HTTP(S), which affects the clone
panel. For example, if:
panel shown to users on a project's page. For example, if:
- Your GitLab instance is at `https://example.com`, then project clone URLs are like
`https://example.com/foo/bar.git`.
@ -284,7 +294,7 @@ panel. For example, if:
you can set this setting to `https://git.example.com/gitlab/`.
To specify a custom Git clone URL for HTTP(S) in `gitlab.rb`, set a new value for
`gitlab_rails['gitlab_ssh_host']`. To specify it from the GitLab UI:
`gitlab_rails['gitlab_ssh_host']`. To specify a new value from the GitLab UI:
Prerequisites:
@ -298,7 +308,7 @@ Prerequisites:
## Configure defaults for RSA, DSA, ECDSA, ED25519, ECDSA_SK, ED25519_SK SSH keys
These options specify the permitted types and lengths for SSH keys.
These options specify the [permitted types and lengths](../../security/ssh_keys_restrictions.md) for SSH keys.
To specify a restriction for each key type:
@ -314,8 +324,6 @@ To specify a restriction for each key type:
- At least 1024 bits.
1. Select **Save changes**.
For more details, see [SSH key restrictions](../../security/ssh_keys_restrictions.md).
## Enable project mirroring
GitLab enables project mirroring by default. If you disable it, both
@ -323,7 +331,7 @@ GitLab enables project mirroring by default. If you disable it, both
[push mirroring](../../user/project/repository/mirror/push.md) no longer
work in every repository. They can only be re-enabled by an administrator user on a per-project basis.
To allow project maintainers on your instance to configure mirroring at the project level:
To allow project maintainers on your instance to configure mirroring per project:
Prerequisites:
@ -340,15 +348,16 @@ Prerequisites:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87579) in GitLab 15.1 [with a flag](../feature_flags.md) named `group_ip_restrictions_allow_global`. Disabled by default.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/366445) in GitLab 15.4. [Feature flag `group_ip_restrictions_allow_global`](https://gitlab.com/gitlab-org/gitlab/-/issues/366445) removed.
Administrators can combine IP address ranges with [group-level IP restrictions](../../user/group/access_and_permissions.md#restrict-group-access-by-ip-address).
Use globally-allowed IP addresses to allow aspects of the GitLab installation to work even when group-level IP address
restrictions are set.
Administrators can combine IP address ranges with
[IP restrictions per group](../../user/group/access_and_permissions.md#restrict-group-access-by-ip-address).
Use globally-allowed IP addresses to allow aspects of the GitLab installation to work even when IP address
restrictions are set per group.
For example, if the GitLab Pages daemon runs on the `10.0.0.0/24` range, you can specify that range as globally-allowed.
This means GitLab Pages can still fetch artifacts from pipelines even if group-level IP address restrictions don't
For example, if the GitLab Pages daemon runs on the `10.0.0.0/24` range, you can specify that range as globally allowed.
GitLab Pages can still fetch artifacts from pipelines, even if IP address restrictions for the group don't
include the `10.0.0.0/24` range.
To add a IP address range to the group-level allowlist:
To add a IP address range to the allowlist for a group:
Prerequisites:

View File

@ -234,7 +234,7 @@ To resolve the issue:
You might get the error `Attempt_Exceed_Limitation - Attempt exceed the limitation, refresh page to try again.` when purchasing compute minutes.
This issue occurs when the credit card form is re-submitted too quickly within a specific timeframe (3 submissions in 1 minute or 6 submissions in 1 hour).
This issue occurs when the credit card form is re-submitted too quickly within a specific time frame (three submissions within one minute or six submissions within one hour).
To resolve this issue, wait a few minutes and try the purchase process again.

View File

@ -61,15 +61,6 @@ You might have jobs or pipelines that run unexpectedly when using `rules:changes
With merged results pipelines, the internal commit that GitLab creates is used as a base to compare against. This commit likely contains more changes than the tip of the MR branch, which causes unexpected outcomes.
### Merged results pipelines are not created
In GitLab 13.7 and earlier, merged results pipelines might not be created due
to a disabled [feature flag](../../user/feature_flags.md). This feature flag
[was removed](https://gitlab.com/gitlab-org/gitlab/-/issues/299115) in GitLab 13.8.
Upgrade to 13.8 or later, or make sure the `:merge_ref_auto_sync`
[feature flag is enabled](../../administration/feature_flags.md#check-if-a-feature-flag-is-enabled)
on your GitLab instance.
### Successful merged results pipeline overrides a failed branch pipeline
A failed branch pipeline is sometimes ignored when the

View File

@ -255,6 +255,7 @@ Git push options can perform actions for merge requests while pushing changes:
| `merge_request.target_project=<project>` | Set the target of the merge request to a particular upstream project, such as: `git push -o merge_request.target_project=path/to/project`. Introduced in [GitLab 16.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132475). |
| `merge_request.merge_when_pipeline_succeeds` | Set the merge request to [merge when its pipeline succeeds](../user/project/merge_requests/merge_when_pipeline_succeeds.md). |
| `merge_request.remove_source_branch` | Set the merge request to remove the source branch when it's merged. |
| `merge_request.squash` | Set the merge request to squash all commits into a single commit on merge Introduced in [GitLab 17.2](https://gitlab.com/gitlab-org/gitlab/-/issues/). |
| `merge_request.title="<title>"` | Set the title of the merge request. For example: `git push -o merge_request.title="The title I want"`. |
| `merge_request.description="<description>"` | Set the description of the merge request. For example: `git push -o merge_request.description="The description I want"`. |
| `merge_request.draft` | Mark the merge request as a draft. For example: `git push -o merge_request.draft`. Introduced in [GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/296673). |

View File

@ -523,7 +523,7 @@ apply, contact [GitLab Support](https://support.gitlab.com/hc/en-us/requests/new
You might get the error `Attempt_Exceed_Limitation - Attempt exceed the limitation, refresh page to try again.` when purchasing a GitLab subscription.
This issue occurs when the credit card form is re-submitted too quickly within a specific timeframe (3 submissions in 1 minute or 6 submissions in 1 hour).
This issue occurs when the credit card form is re-submitted too quickly within a specific time frame (three submissions within one minute or six submissions within one hour).
To resolve this issue, wait a few minutes and try the purchase process again.

View File

@ -501,7 +501,7 @@ apply, contact [GitLab Support](https://support.gitlab.com/hc/en-us/requests/new
You might get the error `Attempt_Exceed_Limitation - Attempt exceed the limitation, refresh page to try again.` when purchasing a GitLab subscription.
This issue occurs when the credit card form is re-submitted too quickly within a specific timeframe (3 submissions in 1 minute or 6 submissions in 1 hour).
This issue occurs when the credit card form is re-submitted too quickly within a specific time frame (three submissions within one minute or six submissions within one hour).
To resolve this issue, wait a few minutes and try the purchase process again.

View File

@ -18,7 +18,7 @@ Learn how to connect GitLab to Google Cloud and create a GitLab pipeline using r
1. Create or select a Google Cloud project.
NOTE:
If you don't plan to keep the resources that you create in this procedure, create a new Google Cloud project instead of selecting an existing project. After you finish these steps, you can delete the project, removing all resources associated with the project.
If you don't plan to keep the resources that you create in this procedure, then create a new Google Cloud project instead of selecting an existing project. After you finish these steps, you can delete the project, removing all resources associated with the project.
To create a Google Cloud project, run the following command:
@ -70,7 +70,7 @@ Learn how to connect GitLab to Google Cloud and create a GitLab pipeline using r
```dockerfile
# Dockerfile for test purposes. Generates a new random image in every build.
FROM alpine:latest
FROM alpine:3.15.11
RUN dd if=/dev/urandom of=random bs=10 count=1
```

View File

@ -52,7 +52,7 @@ DETAILS:
- Helps you write code more efficiently by generating code and showing suggestions as you type.
- Large language model (LLM) for code completion: Vertex AI Codey [`code-gecko`](https://console.cloud.google.com/vertex-ai/publishers/google/model-garden/code-gecko)
- LLM for code generation: Anthropic [`claude-3-sonnet-20240229`](https://console.cloud.google.com/vertex-ai/publishers/anthropic/model-garden/claude-3-sonnet)
- LLM for code generation: Anthropic [`claude-3-5-sonnet-20240620`](https://console.cloud.google.com/vertex-ai/publishers/anthropic/model-garden/claude-3-5-sonnet)
- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Watch overview](https://youtu.be/ds7SG1wgcVM)
- [View documentation](../project/repository/code_suggestions/index.md).

View File

@ -255,5 +255,4 @@ Use the following commands to quickly accomplish specific tasks.
| /tests | [Write tests](#write-tests-in-the-ide) |
| /explain | [Explain code](../gitlab_duo_chat/examples.md#explain-code-in-the-ide) |
| /vulnerability_explain | [Explain current vulnerability](../gitlab_duo/index.md#vulnerability-explanation) |
| | [Explain current vulnerability](../application_security/vulnerabilities/index.md#explaining-a-vulnerability) |
| /refactor | [Refactor the code](../gitlab_duo_chat/examples.md#refactor-code-in-the-ide) |

View File

@ -52,7 +52,6 @@ Because this is an experimental feature,
| `work_item_epics` | Consolidated flag that contains all the changes needed to get epic work items to work for a given group. | Group | **Required** |
| `synced_epic_work_item_editable` | Allows editing epic work items when they have a legacy epic. | Group | **Required** |
| `work_items_rolledup_dates` | Calculates the start and due dates in a hierarchy for work items. | Group | **Required** |
| `epic_and_work_item_labels_unification` | Delegates labels between epics and epic work item. | Group | **Required** |
| `epic_and_work_item_associations_unification` | Delegates other epic and work item associations. | Group | **Required** |
| `epic_and_work_item_notes_unification` | Delegates notes between epics and work item. | Group | **Required** |

View File

@ -59,8 +59,8 @@ The following table lists project permissions available for each role:
<!-- Keep these tables sorted: By category first, then by minimum role, then alphabetically by action. -->
| Action | Guest | Reporter | Developer | Maintainer | Owner | Notes |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------|----------|-----------|------------|-------|-------|
| [Analytics](analytics/index.md):<br>View [issue analytics](group/issues_analytics/index.md) | ✓ | ✓ | ✓ | ✓ | ✓ | |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----:|:--------:|:---------:|:----------:|:-----:|-------|
| [Analytics](analytics/index.md):<br>View [issue analytics](group/issues_analytics/index.md) | ✓ | ✓ | ✓ | ✓ | ✓ | |
| [Analytics](analytics/index.md):<br>View [value stream analytics](group/value_stream_analytics/index.md) | ✓ | ✓ | ✓ | ✓ | ✓ | |
| [Analytics](analytics/index.md):<br>View [DORA metrics](analytics/ci_cd_analytics.md) | | ✓ | ✓ | ✓ | ✓ | |
| [Analytics](analytics/index.md):<br>View [CI/CD analytics](analytics/ci_cd_analytics.md) | | ✓ | ✓ | ✓ | ✓ | |
@ -106,7 +106,7 @@ The following table lists project permissions available for each role:
| [Issues](project/issues/index.md):<br>View [confidential issues](project/issues/confidential_issues.md) | | ✓ | ✓ | ✓ | ✓ | Guest users can only view the [confidential issues](project/issues/confidential_issues.md) they created themselves or are assigned to. |
| [Issues](project/issues/index.md):<br>Close / reopen | | ✓ | ✓ | ✓ | ✓ | Authors and assignees can close and reopen issues even if they don't have the Reporter role. |
| [Issues](project/issues/index.md):<br>Lock threads | | ✓ | ✓ | ✓ | ✓ | |
| [Issues](project/issues/index.md):<br>Manage [related issues](project/issues/related_issues.md) | ✓ | ✓ | ✓ | ✓ | ✓ | |
| [Issues](project/issues/index.md):<br>Manage [related issues](project/issues/related_issues.md) | ✓ | ✓ | ✓ | ✓ | ✓ | |
| [Issues](project/issues/index.md):<br>Manage tracker | | ✓ | ✓ | ✓ | ✓ | |
| [Issues](project/issues/index.md):<br>Move issues | | ✓ | ✓ | ✓ | ✓ | Attached design files are moved together with the issue. |
| [Issues](project/issues/index.md):<br>Set issue [time tracking](project/time_tracking.md) estimate and time spent | | ✓ | ✓ | ✓ | ✓ | |
@ -162,8 +162,8 @@ The following table lists project permissions available for each role:
| [Projects](project/index.md):<br>Disable notification emails | | | | | ✓ | |
| [Projects](project/index.md):<br>Transfer project to another namespace | | | | | ✓ | |
| [Projects](project/index.md): View [Usage Quotas](usage_quotas.md) page | | | | ✓ | ✓ | |
| [Requirements Management](project/requirements/index.md):<br>Archive / reopen | | ✓ | ✓ | ✓ | ✓ | Authors and assignees can archive and re-open even if they dont have the Reporter role. |
| [Requirements Management](project/requirements/index.md):<br>Create / edit | | ✓ | ✓ | ✓ | ✓ | Authors and assignees can modify the title and description even if they dont have the Reporter role.|
| [Requirements Management](project/requirements/index.md):<br>Archive / reopen | | ✓ | ✓ | ✓ | ✓ | Authors and assignees can archive and re-open even if they don't have the Reporter role. |
| [Requirements Management](project/requirements/index.md):<br>Create / edit | | ✓ | ✓ | ✓ | ✓ | Authors and assignees can modify the title and description even if they don't have the Reporter role.|
| [Requirements Management](project/requirements/index.md):<br>Import / export | | ✓ | ✓ | ✓ | ✓ | |
| [Tasks](tasks.md):<br>Add a linked item | ✓ | ✓ | ✓ | ✓ | ✓ | |
| [Tasks](tasks.md):<br>Create | | ✓ | ✓ | ✓ | ✓ | Authors and assignees can modify the title and description even if they don't have the Reporter role. |
@ -181,32 +181,32 @@ The following table lists project permissions available for each role:
Project permissions for [Application Security](application_security/secure_your_application.md) features including dependency management, security analyzers, security policies, and vulnerability management.
| Action | Guest | Reporter | Developer | Maintainer | Owner | Notes |
|--------|:-----:|:--------:|:---------:|:----------:|:-----:|-------|
| View licenses in [dependency list](application_security/dependency_list/index.md) | | | | | | |
| View [dependency list](application_security/dependency_list/index.md) | | | | | | |
| View [vulnerability report](application_security/vulnerability_report/index.md) | | | | | | |
| View [security dashboard](application_security/security_dashboard/index.md) | | | | | | |
| [Create issue](application_security/vulnerabilities/index.md#create-a-gitlab-issue-for-a-vulnerability) from vulnerability finding | | | | | | |
| Manually [create a vulnerability](application_security/vulnerability_report/index.md#manually-add-a-vulnerability) | | | | | | |
| Create and run [on-demand DAST scans](application_security/dast/on-demand_scan.md) | | | | | | |
| Create, edit, delete [individual security policies](application_security/policies/index.md) | | | | | | |
| Create a [CVE ID Request](application_security/cve_id_request.md) | | | | | | |
| Change vulnerability status | | | | | | The `admin_vulnerability` permission was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/412693) from the Developer role in GitLab 17.0. |
| Create or assign [security policy project](application_security/policies/index.md) | | | | | | |
| Manage [security configurations](application_security/configuration/index.md) | | | | | | |
| Action | Guest | Reporter | Developer | Maintainer | Owner | Notes |
|------------------------------------------------------------------------------------------------------------------------------------|:-----:|:--------:|:---------:|:----------:|:-----:|-------|
| View licenses in [dependency list](application_security/dependency_list/index.md) | | | | | | |
| View [dependency list](application_security/dependency_list/index.md) | | | | | | |
| View [vulnerability report](application_security/vulnerability_report/index.md) | | | | | | |
| View [security dashboard](application_security/security_dashboard/index.md) | | | | | | |
| [Create issue](application_security/vulnerabilities/index.md#create-a-gitlab-issue-for-a-vulnerability) from vulnerability finding | | | | | | |
| Manually [create a vulnerability](application_security/vulnerability_report/index.md#manually-add-a-vulnerability) | | | | | | |
| Create and run [on-demand DAST scans](application_security/dast/on-demand_scan.md) | | | | | | |
| Create, edit, delete [individual security policies](application_security/policies/index.md) | | | | | | |
| Create a [CVE ID Request](application_security/cve_id_request.md) | | | | | | |
| Change vulnerability status | | | | | | The `admin_vulnerability` permission was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/412693) from the Developer role in GitLab 17.0. |
| Create or assign [security policy project](application_security/policies/index.md) | | | | | | |
| Manage [security configurations](application_security/configuration/index.md) | | | | | | |
### Compliance
Project permissions for [compliance](compliance/index.md) features including compliance center, audit events, compliance frameworks, and licenses.
| Action | Guest | Reporter | Developer | Maintainer | Owner | Notes |
|-----------------------------------------------------------------------------------------|:-------:|:----------:|:-----------:|:------------:|:-------:|-------|
| View [allowed and denied licenses in MR](compliance/license_scanning_of_cyclonedx_files/index.md) | | | | | | On self-managed GitLab instances, users with the Guest role are able to perform this action only on public and internal projects (not on private projects). [External users](../administration/external_users.md) must be have at least the Reporter role, even if the project is internal. Users with the Guest role on GitLab.com are able to perform this action only on public projects because internal visibility is not available. |
| View [audit events](../administration/audit_event_reports.md) | | | ✓ | ✓ | ✓ | Users can only view events based on their individual actions. |
| View licenses in [dependency list](application_security/dependency_list/index.md) | | | | | | |
| Create, edit, and delete license approval policies | | | ✓ | ✓ | ✓ | |
| Manage [audit streams](compliance/audit_event_streaming.md) | | | | | ✓ | |
| Action | Guest | Reporter | Developer | Maintainer | Owner | Notes |
|---------------------------------------------------------------------------------------------------|:-----:|:--------:|:---------:|:----------:|:-----:|-------|
| View [allowed and denied licenses in MR](compliance/license_scanning_of_cyclonedx_files/index.md) | | | | | | On self-managed GitLab instances, users with the Guest role are able to perform this action only on public and internal projects (not on private projects). [External users](../administration/external_users.md) must be have at least the Reporter role, even if the project is internal. Users with the Guest role on GitLab.com are able to perform this action only on public projects because internal visibility is not available. |
| View [audit events](../administration/audit_event_reports.md) | | | | | | Users can only view events based on their individual actions. |
| View licenses in [dependency list](application_security/dependency_list/index.md) | | | | | | |
| Create, edit, and delete license approval policies | | | | | | |
| Manage [audit streams](compliance/audit_event_streaming.md) | | | | | | |
### Repository
@ -242,7 +242,7 @@ Project permissions for [merge requests](project/merge_requests/index.md):
| Manage [merge request approval rules](project/merge_requests/approvals/rules.md) | | | | ✓ | ✓ | |
| Delete merge request | | | | | ✓ | |
## GitLab CI/CD permissions
### GitLab CI/CD permissions
[GitLab CI/CD](../ci/index.md) permissions for some roles can be modified by these settings:
@ -251,56 +251,59 @@ Project permissions for [merge requests](project/merge_requests/index.md):
- [Pipeline visibility](../ci/pipelines/settings.md#change-pipeline-visibility-for-non-project-members-in-public-projects):
When set to **Everyone with Access**, gives access to certain CI/CD "view" features to *non-project* members.
| Action | Non-member | Guest | Reporter | Developer | Maintainer | Owner | Notes |
|--------------------------------------------------------------------------------------------------------------------------------|------------|-------|----------|-----------|------------|-------|-------|
| See that artifacts exist | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Non-members and guests: Only if the project is public. |
| View a list of jobs | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Non-members: Only if the project is public and **Public pipelines** is enabled in **Project Settings > CI/CD**.<br>Guests: Only if **Public pipelines** is enabled in **Project Settings > CI/CD**. |
| View and download artifacts | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Non-members: Only if the project is public, **Public pipelines** is enabled in **Project Settings > CI/CD**, and [`artifacts:public: false`](../ci/yaml/index.md#artifactspublic) is not set on the job.<br>Guests: Only if **Public pipelines** is enabled in **Project Settings > CI/CD** and `artifacts:public: false` is not set on the job.<br>Reporters: Only if `artifacts:public: false` is not set on the job. |
| View [environments](../ci/environments/index.md) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Non-members and guests: Only if the project is public. |
| View job logs and job details page | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Non-members: Only if the project is public and **Public pipelines** is enabled in **Project Settings > CI/CD**.<br>Guests: Only if **Public pipelines** is enabled in **Project Settings > CI/CD**. |
| View pipelines and pipeline details pages | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Non-members: Only if the project is public and **Public pipelines** is enabled in **Project Settings > CI/CD**.<br>Guests: Only if **Public pipelines** is enabled in **Project Settings > CI/CD**. |
| View pipelines tab in MR | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Non-members and guests: Only if the project is public. |
| [View vulnerabilities in a pipeline](application_security/vulnerability_report/pipeline.md#view-vulnerabilities-in-a-pipeline) | | ✓ | ✓ | ✓ | ✓ | ✓ | Guests: Only if **Public pipelines** is enabled in **Project Settings > CI/CD**. |
| Run deployment job for a protected environment | | | ✓ | ✓ | ✓ | ✓ | Reporters: Only if the user is [part of a group with access to the protected environment](../ci/environments/protected_environments.md#deployment-only-access-to-protected-environments).<br>Developers and maintainers: Only if the user is [allowed to deploy to the protected branch](../ci/environments/protected_environments.md#protecting-environments). |
| View and download project-level [Secure Files](../api/secure_files.md) | | | | ✓ | ✓ | ✓ | |
| Retry jobs | | | | ✓ | ✓ | ✓ | |
| Cancel jobs | | | | ✓ | ✓ | ✓ | Cancellation permissions can be [restricted in the pipeline settings](../ci/pipelines/settings.md#restrict-roles-that-can-cancel-pipelines-or-jobs). |
| Create new [environments](../ci/environments/index.md) | | | | ✓ | ✓ | ✓ | |
| Delete job logs or job artifacts | | | | ✓ | ✓ | ✓ | Developers: Only if the job was triggered by the user and runs for a non-protected branch. |
| Run CI/CD pipeline | | | | ✓ | ✓ | ✓ | |
| Run CI/CD pipeline for a protected branch | | | | ✓ | ✓ | ✓ | Developers and maintainers: Only if the user is [allowed to merge or push to the protected branch](../ci/pipelines/index.md#pipeline-security-on-protected-branches). |
| Stop [environments](../ci/environments/index.md) | | | | ✓ | ✓ | ✓ | |
| View a job with [debug logging](../ci/variables/index.md#enable-debug-logging) | | | | ✓ | ✓ | ✓ | |
| Use pipeline editor | | | | ✓ | ✓ | ✓ | |
| Run [interactive web terminals](../ci/interactive_web_terminal/index.md) | | | | ✓ | ✓ | ✓ | |
| Add project runners to project | | | | | ✓ | ✓ | |
| Clear runner caches manually | | | | | ✓ | ✓ | |
| Enable instance runners in project | | | | | ✓ | ✓ | |
| Manage CI/CD settings | | | | | ✓ | ✓ | |
| Manage job triggers | | | | | ✓ | ✓ | |
| Manage project-level CI/CD variables | | | | | ✓ | ✓ | |
| Manage project-level [Secure Files](../api/secure_files.md) | | | | | ✓ | ✓ | |
| Use [environment terminals](../ci/environments/index.md#web-terminals-deprecated) | | | | | ✓ | ✓ | |
| Delete pipelines | | | | | | ✓ | |
Project Owners can do any listed action, and also can delete pipelines:
### Job permissions
| Action | Non-member | Guest | Reporter | Developer | Maintainer | Notes |
|--------------------------------------------------------------------------------------------------------------------------------|:----------:|:-----:|:--------:|:---------:|:----------:|-------|
| See that artifacts exist | ✓ | ✓ | ✓ | ✓ | ✓ | Non-members and guests: Only if the project is public. |
| View a list of jobs | ✓ | ✓ | ✓ | ✓ | ✓ | Non-members: Only if the project is public and **Public pipelines** is enabled in **Project Settings > CI/CD**.<br>Guests: Only if **Public pipelines** is enabled in **Project Settings > CI/CD**. |
| View and download artifacts | ✓ | ✓ | ✓ | ✓ | ✓ | Non-members: Only if the project is public, **Public pipelines** is enabled in **Project Settings > CI/CD**, and [`artifacts:public: false`](../ci/yaml/index.md#artifactspublic) is not set on the job.<br>Guests: Only if **Public pipelines** is enabled in **Project Settings > CI/CD** and `artifacts:public: false` is not set on the job.<br>Reporters: Only if `artifacts:public: false` is not set on the job. |
| View [environments](../ci/environments/index.md) | ✓ | ✓ | ✓ | ✓ | ✓ | Non-members and guests: Only if the project is public. |
| View job logs and job details page | ✓ | ✓ | ✓ | ✓ | ✓ | Non-members: Only if the project is public and **Public pipelines** is enabled in **Project Settings > CI/CD**.<br>Guests: Only if **Public pipelines** is enabled in **Project Settings > CI/CD**. |
| View pipelines and pipeline details pages | ✓ | ✓ | ✓ | ✓ | ✓ | Non-members: Only if the project is public and **Public pipelines** is enabled in **Project Settings > CI/CD**.<br>Guests: Only if **Public pipelines** is enabled in **Project Settings > CI/CD**. |
| View pipelines tab in MR | ✓ | ✓ | ✓ | ✓ | ✓ | Non-members and guests: Only if the project is public. |
| [View vulnerabilities in a pipeline](application_security/vulnerability_report/pipeline.md#view-vulnerabilities-in-a-pipeline) | | ✓ | ✓ | ✓ | ✓ | Guests: Only if **Public pipelines** is enabled in **Project Settings > CI/CD**. |
| Run deployment job for a protected environment | | | ✓ | ✓ | ✓ | Reporters: Only if the user is [part of a group with access to the protected environment](../ci/environments/protected_environments.md#deployment-only-access-to-protected-environments).<br>Developers and maintainers: Only if the user is [allowed to deploy to the protected branch](../ci/environments/protected_environments.md#protecting-environments). |
| View and download project [Secure Files](../api/secure_files.md) | | | | ✓ | ✓ | |
| Retry jobs | | | | ✓ | ✓ | |
| Cancel jobs | | | | ✓ | ✓ | Cancellation permissions can be [restricted in the pipeline settings](../ci/pipelines/settings.md#restrict-roles-that-can-cancel-pipelines-or-jobs). |
| Create new [environments](../ci/environments/index.md) | | | | ✓ | ✓ | |
| Delete job logs or job artifacts | | | | ✓ | ✓ | Developers: Only if the job was triggered by the user and runs for a non-protected branch. |
| Run CI/CD pipeline | | | | ✓ | ✓ | |
| Run CI/CD job | | | | ✓ | ✓ | |
| Run CI/CD pipeline for a protected branch | | | | ✓ | ✓ | Developers and maintainers: Only if the user is [allowed to merge or push to the protected branch](../ci/pipelines/index.md#pipeline-security-on-protected-branches). |
| Stop [environments](../ci/environments/index.md) | | | | ✓ | ✓ | |
| View a job with [debug logging](../ci/variables/index.md#enable-debug-logging) | | | | ✓ | ✓ | |
| Use pipeline editor | | | | ✓ | ✓ | |
| Run [interactive web terminals](../ci/interactive_web_terminal/index.md) | | | | ✓ | ✓ | |
| Add project runners to project | | | | | ✓ | |
| Clear runner caches manually | | | | | ✓ | |
| Enable instance runners in project | | | | | ✓ | |
| Manage CI/CD settings | | | | | ✓ | |
| Manage job triggers | | | | | ✓ | |
| Manage project CI/CD variables | | | | | ✓ | |
| Manage project [Secure Files](../api/secure_files.md) | | | | | ✓ | |
| Use [environment terminals](../ci/environments/index.md#web-terminals-deprecated) | | | | | ✓ | |
This table shows granted privileges for jobs triggered by specific types of users:
#### Job permissions
| Action | Guest, Reporter | Developer | Maintainer | Administrator | Notes |
|----------------------------------------------|-----------------|-----------|------------|---------------|-------|
| Run CI job | | ✓ | ✓ | ✓ | |
| Clone source and LFS from current project | | ✓ | ✓ | ✓ | |
| Clone source and LFS from public projects | | ✓ | ✓ | ✓ | |
| Clone source and LFS from internal projects | | ✓ | ✓ | ✓ | Developers and Maintainers: Only if the triggering user is not an external user. |
| Clone source and LFS from private projects | | ✓ | ✓ | ✓ | Only if the triggering user is a member of the project. See also [Usage of private Docker images with `if-not-present` pull policy](https://docs.gitlab.com/runner/security/index.html#usage-of-private-docker-images-with-if-not-present-pull-policy). |
| Pull container images from current project | | ✓ | ✓ | ✓ | |
| Pull container images from public projects | | ✓ | ✓ | ✓ | |
| Pull container images from internal projects | | ✓ | ✓ | ✓ | Developers and Maintainers: Only if the triggering user is not an external user. |
| Pull container images from private projects | | ✓ | ✓ | ✓ | Only if the triggering user is a member of the project. See also [Usage of private Docker images with `if-not-present` pull policy](https://docs.gitlab.com/runner/security/index.html#usage-of-private-docker-images-with-if-not-present-pull-policy). |
| Push container images to current project | | ✓ | ✓ | ✓ | |
| Push container images to other projects | | | | | |
| Push source and LFS | | | | | |
This table shows granted privileges for jobs triggered by specific roles.
Project Owners can do any listed action, but no users can push source and LFS together.
| Action | Developer | Maintainer | Notes |
|----------------------------------------------|:---------:|:----------:|-------|
| Clone source and LFS from current project | ✓ | ✓ | |
| Clone source and LFS from public projects | ✓ | ✓ | |
| Clone source and LFS from internal projects | ✓ | ✓ | Developers and Maintainers: Only if the triggering user is not an external user. |
| Clone source and LFS from private projects | ✓ | ✓ | Only if the triggering user is a member of the project. See also [Usage of private Docker images with `if-not-present` pull policy](https://docs.gitlab.com/runner/security/index.html#usage-of-private-docker-images-with-if-not-present-pull-policy). |
| Pull container images from current project | ✓ | ✓ | |
| Pull container images from public projects | ✓ | ✓ | |
| Pull container images from internal projects | ✓ | ✓ | Developers and Maintainers: Only if the triggering user is not an external user. |
| Pull container images from private projects | ✓ | ✓ | Only if the triggering user is a member of the project. See also [Usage of private Docker images with `if-not-present` pull policy](https://docs.gitlab.com/runner/security/index.html#usage-of-private-docker-images-with-if-not-present-pull-policy). |
| Push container images to current project | ✓ | ✓ | You cannot push container images to other projects. |
Guest users and members with the Reporter role cannot do any of these actions.
## Group members permissions
@ -321,7 +324,7 @@ The following table lists group permissions available for each role:
| View [group wiki](project/wiki/group.md) pages | ✓ | ✓ | ✓ | ✓ | ✓ | Guests: In addition, if your group is public or internal, all users who can see the group can also see group wiki pages. |
| View [Insights](project/insights/index.md) | ✓ | ✓ | ✓ | ✓ | ✓ | |
| View [Insights](project/insights/index.md) charts | ✓ | ✓ | ✓ | ✓ | ✓ | |
| View [Issue analytics](group/issues_analytics/index.md) | ✓ | ✓ | ✓ | ✓ | ✓ | |
| View [Issue analytics](group/issues_analytics/index.md) | ✓ | ✓ | ✓ | ✓ | ✓ | |
| View Contribution analytics | ✓ | ✓ | ✓ | ✓ | ✓ | |
| View group [epic](group/epics/index.md) | ✓ | ✓ | ✓ | ✓ | ✓ | |
| View value stream analytics | ✓ | ✓ | ✓ | ✓ | ✓ | |
@ -369,7 +372,7 @@ The following table lists group permissions available for each role:
| [Migrate groups](group/import/index.md) | | | | | ✓ | |
| Purge the dependency proxy for a group | | | | | ✓ | |
| Share (invite) groups with groups | | | | | ✓ | |
| View [Billing](../subscriptions/gitlab_com/index.md#view-your-gitlabcom-subscription) | | | | | ✓ | Does not apply to subgroups |
| View [Billing](../subscriptions/gitlab_com/index.md#view-your-gitlabcom-subscription) | | | | | ✓ | Does not apply to subgroups |
| View 2FA status of members | | | | | ✓ | |
| View group [Usage Quotas](usage_quotas.md) page | | | | | ✓ | Does not apply to subgroups |
| Map or unmap workspace cluster agents to and from a group | | | | | ✓ | |
@ -390,14 +393,14 @@ Group permissions for [Application Security](application_security/secure_your_ap
Groups permissions for [compliance](compliance/index.md) features including compliance center, audit events, compliance frameworks, and licenses.
| Action | Guest | Reporter | Developer | Maintainer | Owner | Notes |
|-----------------------------------------------------------------------------------------|:-------:|:----------:|:-----------:|:------------:|:-------:|-------|
| View [audit events](../administration/audit_event_reports.md) | | | ✓ | ✓ | ✓ | Users can view only events based on their individual actions. |
| View licenses in the [dependency list](application_security/dependency_list/index.md) | | | | | | |
| Manage [audit streams](compliance/audit_event_streaming.md) | | | | | ✓ | |
| View the [compliance center](compliance/compliance_center/index.md) | | | | | ✓ | |
| Manage [compliance frameworks](group/compliance_frameworks.md) | | | | | ✓ | |
| Assign [compliance frameworks](group/compliance_frameworks.md) to projects | | | | | ✓ | |
| Action | Guest | Reporter | Developer | Maintainer | Owner | Notes |
|---------------------------------------------------------------------------------------|:-----:|:--------:|:---------:|:----------:|:-----:|-------|
| View [audit events](../administration/audit_event_reports.md) | | | | | | Users can view only events based on their individual actions. |
| View licenses in the [dependency list](application_security/dependency_list/index.md) | | | | | | |
| Manage [audit streams](compliance/audit_event_streaming.md) | | | | | | |
| View the [compliance center](compliance/compliance_center/index.md) | | | | | | |
| Manage [compliance frameworks](group/compliance_frameworks.md) | | | | | | |
| Assign [compliance frameworks](group/compliance_frameworks.md) to projects | | | | | | |
### Repository

View File

@ -15,7 +15,7 @@ easier for unauthorized people to sign in to your account.
Some organizations require you to meet certain requirements when choosing a password.
Improve the security of your account with [two-factor authentication](account/two_factor_authentication.md)
Improve the security of your account with [two-factor authentication](account/two_factor_authentication.md).
## Choose your password

View File

@ -112,11 +112,11 @@ To auto-format this table, use the VS Code Markdown Table formatter: `https://do
| `/remove_zoom` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Remove Zoom meeting from this issue. |
| `/reopen` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Reopen. |
| `/severity <severity>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Set the severity. Issue type must be `Incident`. Options for `<severity>` are `S1` ... `S4`, `critical`, `high`, `medium`, `low`, `unknown`. |
| `/shrug <comment>` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Append the comment with `¯\_(ツ)_/¯`. |
| `/shrug` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Add `¯\_(ツ)_/¯`. |
| `/spend <time> [<date>]` or `/spend_time <time> [<date>]` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Add or subtract spent time. Optionally, specify the date that time was spent on. For example, `/spend 1mo 2w 3d 4h 5m 2018-08-26` or `/spend -1h 30m`. For more information, see [Time tracking](time_tracking.md). Alias `/spend_time` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16501) in GitLab 15.6. |
| `/submit_review` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Submit a pending review. |
| `/subscribe` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Subscribe to notifications. |
| `/tableflip <comment>` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Append the comment with `(╯°□°)╯︵ ┻━┻`. |
| `/tableflip` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Add `(╯°□°)╯︵ ┻━┻`. |
| `/target_branch <local branch name>` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Set target branch. |
| `/timeline <timeline comment> \| <date(YYYY-MM-DD)> <time(HH:MM)>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Add a timeline event to this incident. For example, `/timeline DB load spiked \| 2022-09-07 09:30`. ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/368721) in GitLab 15.4). |
| `/title <new title>` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Change title. |
@ -172,9 +172,9 @@ To auto-format this table, use the VS Code Markdown Table formatter: `https://do
| `/remove_parent` | **{check-circle}** Yes | **{dotted-circle}** No | **{check-circle}** Yes | Removes the parent work item. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/434344) in GitLab 16.9. |
| `/reopen` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Reopen. |
| `/set_parent <work_item>` | **{check-circle}** Yes | **{dotted-circle}** No | **{check-circle}** Yes | Set parent work item to `<work_item>`. The `<work_item>` value should be in the format of `#iid`, `group/project#iid`, or a URL to a work item. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/420798) in GitLab 16.5. |
| `/shrug <comment>` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Append the comment with `¯\_(ツ)_/¯`. |
| `/shrug` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Add `¯\_(ツ)_/¯`. |
| `/subscribe` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Subscribe to notifications. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/420796) in GitLab 16.4 |
| `/tableflip <comment>` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Append the comment with `(╯°□°)╯︵ ┻━┻`. |
| `/tableflip` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Add `(╯°□°)╯︵ ┻━┻`. |
| `/title <new title>` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Change title. |
| `/todo` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Add a to-do item. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/412277) in GitLab 16.2. |
| `/type` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Converts work item to specified type. Available options for `<type>` include `issue`, `task`, `objective` and `key result`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/385227) in GitLab 16.0. |

View File

@ -182,8 +182,11 @@ For more information, see the [VS Code documentation](https://code.visualstudio.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/385157) in GitLab 17.2.
The GitLab Workflow extension for VS Code is configured by default in workspaces.
With this extension, you can view issues, create and review merge requests, and manage CI/CD pipelines.
The extension also powers AI features like GitLab Duo Code Suggestions and GitLab Duo Chat.
With this extension, you can view issues, create merge requests, and manage CI/CD pipelines.
This extension also powers AI features like [GitLab Duo Code Suggestions](../project/repository/code_suggestions/index.md)
and [GitLab Duo Chat](../gitlab_duo_chat/index.md).
For more information, see [GitLab Workflow extension for VS Code](https://gitlab.com/gitlab-org/gitlab-vscode-extension).
## Extension marketplace
@ -196,6 +199,7 @@ For more information, see the history.
When `allow_extensions_marketplace_in_workspace` is enabled, you can use the extension marketplace in workspaces.
An administrator can enable or disable the flag for top-level groups only.
The extension marketplace connects to the [Open VSX Registry](https://open-vsx.org/).
## Personal access token
@ -203,8 +207,10 @@ The extension marketplace connects to the [Open VSX Registry](https://open-vsx.o
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/129715) in GitLab 16.4.
> - `api` permission [added](https://gitlab.com/gitlab-org/gitlab/-/issues/385157) in GitLab 17.2.
When you [create a workspace](configuration.md#create-a-workspace), you get a personal access token with `write_repository` and `api` permissions.
This token is used to initially clone the project while starting the workspace and to configure the GitLab Workflow extension for VS Code.
When you [create a workspace](configuration.md#create-a-workspace), you get a personal access token
with `write_repository` and `api` permissions.
This token is used to initially clone the project while starting the workspace
and to configure the GitLab Workflow extension for VS Code.
Any Git operation you perform in the workspace uses this token for authentication and authorization.
When you terminate the workspace, the token is revoked.

View File

@ -38,13 +38,14 @@ module Banzai
private
def render_options
return OPTIONS unless sourcepos_disabled? || headers_disabled? || autolink_disabled?
return OPTIONS unless sourcepos_disabled? || headers_disabled? || autolink_disabled? || raw_html_disabled?
OPTIONS.merge(
sourcepos: !sourcepos_disabled?,
header_ids: headers_disabled? ? nil : OPTIONS[:header_ids],
autolink: !autolink_disabled?,
relaxed_autolinks: !autolink_disabled?
relaxed_autolinks: !autolink_disabled?,
unsafe: !raw_html_disabled?
)
end
@ -55,6 +56,10 @@ module Banzai
def autolink_disabled?
context[:autolink] == false
end
def raw_html_disabled?
context[:disable_raw_html]
end
end
end
end

View File

@ -15,6 +15,10 @@ module Banzai
Filter::QuickActionFilter
]
end
def self.transform_context(context)
context.merge(disable_raw_html: true)
end
end
end
end

View File

@ -46,6 +46,7 @@ module Gitlab
def by_custom_domain(host)
domain = PagesDomain.find_by_domain_case_insensitive(host)
return unless domain&.enabled?
return unless domain&.pages_deployed?
::Pages::VirtualDomain.new(projects: [domain.project], domain: domain)

View File

@ -13,6 +13,7 @@ module Gitlab
:merge_when_pipeline_succeeds,
:milestone,
:remove_source_branch,
:squash,
:target,
:target_project,
:title,

View File

@ -94,8 +94,8 @@ module Gitlab
# use a markdown based pipeline to grab possible paragraphs that might
# contain quick actions. This ensures they are not in HTML blocks, quote blocks,
# or code blocks.
pipeline = Banzai::Pipeline::QuickActionPipeline.html_pipeline
possible_paragraphs = pipeline.call(content, {}, {})[:quick_action_paragraphs]
pipeline = Banzai::Pipeline::QuickActionPipeline
possible_paragraphs = pipeline.call(content, {})[:quick_action_paragraphs]
if possible_paragraphs.present?
content_lines = content.lines

View File

@ -211,18 +211,16 @@ module Gitlab
end
end
desc { _("Append the comment with %{shrug}") % { shrug: SHRUG } }
params '<Comment>'
desc { _("Add %{shrug}") % { shrug: SHRUG } }
types ::Issuable
substitution :shrug do |comment|
"#{comment} #{SHRUG}"
substitution :shrug do
SHRUG
end
desc { _("Append the comment with %{tableflip}") % { tableflip: TABLEFLIP } }
params '<Comment>'
desc { _("Add %{tableflip}") % { tableflip: TABLEFLIP } }
types ::Issuable
substitution :tableflip do |comment|
"#{comment} #{TABLEFLIP}"
substitution :tableflip do
TABLEFLIP
end
desc { _('Set severity') }

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
require_relative 'tokens/manage_expiry_task'
namespace :gitlab do
namespace :tokens do
desc 'GitLab | Tokens | Show information about tokens'
task analyze: :environment do |_t, _args|
Tasks::Gitlab::Tokens::ManageExpiryTask.new.analyze
end
desc 'GitLab | Tokens | Edit expiration dates for tokens'
task edit: :environment do |_t, _args|
Tasks::Gitlab::Tokens::ManageExpiryTask.new.edit
end
end
end

View File

@ -0,0 +1,203 @@
# frozen_string_literal: true
require 'tty-prompt'
module Tasks
module Gitlab
module Tokens
class ManageExpiryTask
TOTAL_WIDTH = 70
def analyze
show_pat_expires_at_migration_status
show_most_common_pat_expiration_dates
end
def edit
loop do
analyze
break unless prompt_action
end
end
private
def show_pat_expires_at_migration_status
sql = <<~SQL
SELECT * FROM batched_background_migrations
WHERE job_class_name = 'CleanupPersonalAccessTokensWithNilExpiresAt'
AND table_name = 'personal_access_tokens'
AND column_name = 'id'
SQL
print_header("Personal/Project/Group Access Token Expiration Migration")
base_model = ::Gitlab::Database.database_base_models[::Gitlab::Database::MAIN_DATABASE_NAME]
record = base_model.connection.select_one(sql)
if record
puts "Started at: #{record['started_at']}"
puts "Finished : #{record['finished_at']}"
else
puts "Status: Not run"
end
end
def show_most_common_pat_expiration_dates
print_header "Top 10 Personal/Project/Group Access Token Expiration Dates"
puts "| Expiration Date | Count |"
puts "|-----------------|-------|"
with_most_common_pat_expiration_dates do |row|
expiry_date = row[:expires_at] || "(none)"
puts "| #{expiry_date.to_s.ljust(15)} | #{row[:count].to_s.ljust(5)} |"
end
print_footer
end
def with_most_common_pat_expiration_dates
# rubocop:disable CodeReuse/ActiveRecord -- Rake task specifically for fixing an issue
ApplicationRecord.with_fast_read_statement_timeout(0) do # rubocop: disable Performance/ActiveRecordSubtransactionMethods -- no subtransaction here
PersonalAccessToken
.select(:expires_at, Arel.sql('count(*)'))
.group(:expires_at)
.order(Arel.sql('count(*) DESC'))
.order(expires_at: :desc)
.limit(10)
.each do |row|
yield row
end
end
# rubocop:enable CodeReuse/ActiveRecord
end
def prompt_action
prompt = TTY::Prompt.new
puts ""
user_choice = prompt.select("What do you want to do?") do |menu|
menu.enum "."
menu.choice "Extend expiration date", 1
menu.choice "Remove expiration date", 2
menu.choice "Quit", 3
end
case user_choice
when 1
extend_expiration_date
true
when 2
remove_expiration_date
true
when 3
false
end
end
def extend_expiration_date
old_date = prompt_expiration_date_selection
return unless old_date
prompt = TTY::Prompt.new
num_days = ::Gitlab::CurrentSettings.max_personal_access_token_lifetime || 365
new_date = old_date + num_days.days
new_date = prompt.ask("What would you like the new expiration date to be?", default: new_date)
new_date = Date.parse(new_date) unless new_date.is_a?(Date)
puts ""
puts "Old expiration date: #{old_date}"
puts "New expiration date: #{new_date}"
confirmed = prompt.yes?(
"WARNING: This will now update #{token_count(old_date)} token(s). Are you sure?",
default: false
)
if confirmed
puts "Updating tokens..."
update_tokens_with_expiration(old_date, new_date)
else
puts "Aborting!"
end
rescue Date::Error
puts "Invalid date, aborting..."
end
def remove_expiration_date
old_date = prompt_expiration_date_selection
return unless old_date
prompt = TTY::Prompt.new
puts ""
puts "WARNING: This will remove the expiration for tokens that expire on #{old_date}."
confirmed = prompt.yes?("This will affect #{token_count(old_date)} tokens. Are you sure?", default: false)
if confirmed
update_tokens_with_expiration(old_date, nil)
else
puts "Aborting!"
end
end
def update_tokens_with_expiration(old_date, new_date)
total = 0
# rubocop:disable CodeReuse/ActiveRecord -- Rake task specifically for fixing an issue
PersonalAccessToken.where(expires_at: old_date).each_batch do |batch|
puts "Updating personal access tokens from ID #{batch.minimum(:id)} to #{batch.maximum(:id)}..."
total += batch.update_all(expires_at: new_date)
end
# rubocop:enable CodeReuse/ActiveRecord -- Rake task specifically for fixing an issue
puts "Updated #{total} tokens!"
end
def prompt_expiration_date_selection
prompt = TTY::Prompt.new
choices = []
with_most_common_pat_expiration_dates do |row|
choices << row[:expires_at] if row[:expires_at]
end
abort_choice = "--> Abort"
choices << abort_choice
selection = prompt.select("Select an expiration date", choices)
selection == abort_choice ? nil : selection
end
def token_count(expiration_date)
# rubocop:disable CodeReuse/ActiveRecord -- Rake task specifically for fixing an issue
ApplicationRecord.with_fast_read_statement_timeout(0) do # rubocop: disable Performance/ActiveRecordSubtransactionMethods -- no subtransaction here
PersonalAccessToken.where(expires_at: expiration_date).count
end
# rubocop:enable CodeReuse/ActiveRecord
end
def print_header(title, total_width = TOTAL_WIDTH)
title_length = title.length
side_length = (total_width - title_length) / 2
left_side = "=" * side_length
right_side = "=" * (side_length + (total_width % 2))
header = "#{left_side} #{title} #{right_side}"
puts header
end
def print_footer
# Account for the spaces between the "=" in the header
puts "=" * (TOTAL_WIDTH + 2)
end
end
end
end
end

View File

@ -3002,6 +3002,12 @@ msgstr ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
msgid "Add %{shrug}"
msgstr ""
msgid "Add %{tableflip}"
msgstr ""
msgid "Add CHANGELOG"
msgstr ""
@ -6295,12 +6301,6 @@ msgstr ""
msgid "AppearanceSettings|Preview last save:"
msgstr ""
msgid "Append the comment with %{shrug}"
msgstr ""
msgid "Append the comment with %{tableflip}"
msgstr ""
msgid "Append the hostname of your GitLab instance to the status check name."
msgstr ""

View File

@ -11,6 +11,9 @@ FactoryBot.define do
dist: {
tarball: 'http://localhost/tarball.tgz',
shasum: '1234567890'
},
scripts: {
test: 'echo "Test"'
}
}
end

View File

@ -1,7 +0,0 @@
# frozen_string_literal: true
class OrderingTestOne < Gitlab::Database::Migration[2.1]
def change
# no op
end
end

View File

@ -1,7 +0,0 @@
# frozen_string_literal: true
class OrderingTestTwo < Gitlab::Database::Migration[2.1]
def change
# no op
end
end

View File

@ -93,7 +93,7 @@ RSpec.describe LooksAhead do
end
before_all do
stub_feature_flags(epic_and_work_item_labels_unification: false)
stub_feature_flags(epic_and_work_item_associations_unification: false)
end
def run_query(gql_query)

View File

@ -47,7 +47,7 @@ RSpec.describe Banzai::Pipeline::QuickActionPipeline, feature_category: :team_pl
.to match_array [{ start_line: 0, end_line: 2 }, { start_line: 8, end_line: 8 }]
end
it 'does not a quick action in a code block' do
it 'does not detect a quick action in a code block' do
markdown = <<~MD.strip
```
Lorem ipsum
@ -59,4 +59,15 @@ RSpec.describe Banzai::Pipeline::QuickActionPipeline, feature_category: :team_pl
expect(result[:quick_action_paragraphs]).to be_empty
end
it 'does not detect a quick action in raw html with a sourcepos' do
markdown = <<~MD.strip
<p data-sourcepos="0:1-2:10">
/quick
</p>
MD
result = described_class.call(markdown, project: nil)
expect(result[:quick_action_paragraphs]).to be_empty
end
end

View File

@ -30,11 +30,19 @@ RSpec.describe Gitlab::Pages::VirtualHostFinder, feature_category: :pages do
create(:pages_deployment, project: project)
end
it 'returns the virual domain when there are pages deployed for the project' do
it 'returns the virtual domain' do
expect(virtual_domain).to be_an_instance_of(Pages::VirtualDomain)
expect(virtual_domain.lookup_paths.length).to eq(1)
expect(virtual_domain.lookup_paths.first.project_id).to eq(project.id)
end
context 'when the domain is disabled' do
let_it_be(:pages_domain) { create(:pages_domain, :disabled, project: project) }
it 'does not return the virtual domain' do
expect(virtual_domain).to be_nil
end
end
end
end

View File

@ -15,8 +15,8 @@ RSpec.describe Gitlab::QuickActions::Extractor, feature_category: :team_planning
command(:power) {}
command(:noop_command)
substitution(:substitution) { 'foo' }
substitution :shrug do |comment|
"#{comment} SHRUG"
substitution :shrug do
"SHRUG"
end
end.command_definitions
end
@ -241,15 +241,15 @@ RSpec.describe Gitlab::QuickActions::Extractor, feature_category: :team_planning
msg, commands = extractor.extract_commands(msg)
expect(commands).to eq [['reopen'], ['shrug', 'this is great?']]
expect(msg).to eq "hello\nworld\nthis is great? SHRUG"
expect(msg).to eq "hello\nworld\nSHRUG"
end
it 'extracts and performs multiple substitution commands' do
msg = %(hello\nworld\n/reopen\n/shrug this is great?\n/shrug meh)
msg = %(hello\nworld\n/reopen\n/shrug this is great?\n/shrug)
msg, commands = extractor.extract_commands(msg)
expect(commands).to eq [['reopen'], ['shrug', 'this is great?'], %w[shrug meh]]
expect(msg).to eq "hello\nworld\nthis is great? SHRUG\nmeh SHRUG"
expect(commands).to eq [['reopen'], ['shrug', 'this is great?'], ['shrug']]
expect(msg).to eq "hello\nworld\nSHRUG\nSHRUG"
end
it 'does not extract substitution command in inline code' do
@ -265,7 +265,7 @@ RSpec.describe Gitlab::QuickActions::Extractor, feature_category: :team_planning
msg, commands = extractor.extract_commands(msg)
expect(commands).to eq [['reopen'], ['shrug', 'this is great?']]
expect(msg).to eq "hello\nworld\nthis is great? SHRUG"
expect(msg).to eq "hello\nworld\nSHRUG"
end
it 'extracts and performs substitution commands with comments' do
@ -336,6 +336,7 @@ RSpec.describe Gitlab::QuickActions::Extractor, feature_category: :team_planning
context 'does not extract commands inside' do
where(:description, :text) do
'block HTML tags' | "Hello\r\n<div>\r\nText\r\n/close\r\n/assign @user\r\n</div>\r\n\r\nWorld"
'raw HTML with sourcepos' | "<p data-sourcepos=\"0:1-2:10\">\r\n/close\r\n</p>"
'inline html on seperated rows' | "Text\r\n<b>\r\n/close\r\n</b>"
'HTML comments' | "<!--\n/assign @user\n-->"
'blockquotes' | "> Text\r\n/reopen"

View File

@ -61,4 +61,12 @@ RSpec.describe Packages::Npm::Metadatum, type: :model, feature_category: :packag
end
end
end
describe '#package_json_scripts' do
let(:metadatum) { build_stubbed(:npm_metadatum) }
subject { metadatum.package_json_scripts }
it { is_expected.to eq({ 'test' => 'echo "Test"' }) }
end
end

View File

@ -5,12 +5,12 @@ require 'spec_helper'
RSpec.describe GlobalPolicy, feature_category: :shared do
include TermsHelper
HasUserType::BOT_USER_TYPES.each do |type| # rubocop:disable RSpec/UselessDynamicDefinition -- False positive
type_sym = type.to_sym
let_it_be(type_sym) { create(:user, type_sym) }
end
let_it_be(:admin_user) { create(:admin) }
let_it_be(:project_bot) { create(:user, :project_bot) }
let_it_be(:service_account) { create(:user, :service_account) }
let_it_be(:migration_bot) { create(:user, :migration_bot) }
let_it_be(:security_bot) { create(:user, :security_bot) }
let_it_be(:llm_bot) { create(:user, :llm_bot) }
let_it_be_with_reload(:current_user) { create(:user) }
let_it_be(:user) { create(:user) }
@ -705,6 +705,32 @@ RSpec.describe GlobalPolicy, feature_category: :shared do
end
end
describe 'use_quick_actions' do
HasUserType::BOT_USER_TYPES.each do |bot|
context "with #{bot}" do
let(:current_user) { public_send(bot) }
if bot.in?(%w[alert_bot project_bot support_bot admin_bot service_account])
it { is_expected.to be_allowed(:use_quick_actions) }
else
it { is_expected.to be_disallowed(:use_quick_actions) }
end
end
end
context 'with regular user' do
let(:current_user) { user }
it { is_expected.to be_allowed(:use_quick_actions) }
end
context 'with anonymous' do
let(:current_user) { nil }
it { is_expected.to be_disallowed(:use_quick_actions) }
end
end
describe 'create_organization' do
context 'with regular user' do
let(:current_user) { user }

View File

@ -1458,5 +1458,12 @@ RSpec.describe Issues::UpdateService, :mailer, feature_category: :team_planning
let(:existing_issue) { create(:issue, project: project) }
let(:issuable) { described_class.new(container: project, current_user: user, params: params).execute(existing_issue) }
end
it_behaves_like 'issuable record does not run quick actions when not editing description' do
let(:label) { create(:label, project: project) }
let(:assignee) { create(:user, maintainer_of: project) }
let(:existing_issue) { create(:issue, project: project, description: old_description) }
let(:updated_issuable) { described_class.new(container: project, current_user: user, params: params).execute(existing_issue) }
end
end
end

View File

@ -391,7 +391,9 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state, f
}
end
let(:issuable) { described_class.new(project: project, current_user: user, params: params).execute }
let(:issuable) do
described_class.new(project: project, current_user: user, params: params.merge(default_params)).execute
end
end
context 'Quick actions' do

View File

@ -22,6 +22,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService, feature_category: :sour
let(:title) { 'my title' }
let(:draft_title) { 'Draft: my title' }
let(:draft) { true }
let(:squash) { true }
let(:description) { 'my description' }
let(:multiline_description) do
<<~MD.chomp
@ -105,6 +106,16 @@ RSpec.describe MergeRequests::PushOptionsHandlerService, feature_category: :sour
end
end
shared_examples_for 'a service that can set a merge request to be squashed' do
subject(:last_mr) { MergeRequest.last }
it 'sets the squash property' do
service.execute
expect(last_mr.squash).to eq(squash)
end
end
shared_examples_for 'a service that can set the milestone of a merge request' do
subject(:last_mr) { MergeRequest.last }
@ -572,6 +583,71 @@ RSpec.describe MergeRequests::PushOptionsHandlerService, feature_category: :sour
it_behaves_like 'with the project default branch'
end
describe '`squash` push option' do
let(:push_options) { { squash: squash } }
context 'with a new branch' do
let(:changes) { new_branch_changes }
it_behaves_like 'a service that does not create a merge request'
it 'adds an error to the service' do
service.execute
expect(service.errors).to include(error_mr_required)
end
context 'when coupled with the `create` push option' do
let(:push_options) { { create: true, squash: squash } }
it_behaves_like 'a service that can create a merge request'
it_behaves_like 'a service that can set a merge request to be squashed'
context 'when squash is false' do
let(:squash) { false }
it_behaves_like 'a service that can set a merge request to be squashed'
end
end
end
context 'with an existing branch but no open MR' do
let(:changes) { existing_branch_changes }
it_behaves_like 'a service that does not create a merge request'
it 'adds an error to the service' do
service.execute
expect(service.errors).to include(error_mr_required)
end
context 'when coupled with the `create` push option' do
let(:push_options) { { create: true, squash: squash } }
it_behaves_like 'a service that can create a merge request'
it_behaves_like 'a service that can set a merge request to be squashed'
context 'when squash is false' do
let(:squash) { false }
it_behaves_like 'a service that can set a merge request to be squashed'
end
end
end
context 'with an existing branch that has a merge request open' do
let(:changes) { existing_branch_changes }
let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch) }
it_behaves_like 'a service that does not create a merge request'
it_behaves_like 'a service that can set a merge request to be squashed'
end
it_behaves_like 'with a deleted branch'
it_behaves_like 'with the project default branch'
end
describe '`label` push option' do
let(:push_options) { { label: { label1 => 1, label2 => 1 } } }

View File

@ -1383,6 +1383,13 @@ RSpec.describe MergeRequests::UpdateService, :mailer, feature_category: :code_re
let(:issuable) { described_class.new(project: project, current_user: user, params: params).execute(existing_merge_request) }
end
it_behaves_like 'issuable record does not run quick actions when not editing description' do
let(:label) { create(:label, project: project) }
let(:assignee) { create(:user, maintainer_of: project) }
let(:existing_merge_request) { create(:merge_request, source_project: project, description: old_description) }
let(:updated_issuable) { described_class.new(project: project, current_user: user, params: params).execute(existing_merge_request) }
end
context 'updating labels' do
context 'when merge request is not merged' do
let(:label_a) { label }

View File

@ -387,7 +387,7 @@ RSpec.describe Notes::QuickActionsService, feature_category: :team_planning do
let_it_be(:child) { create(:work_item, :objective, project: project) }
let_it_be(:second_child) { create(:work_item, :objective, project: project) }
let_it_be(:note_text) { "/add_child #{child.to_reference}, #{second_child.to_reference}" }
let_it_be(:note) { create(:note, noteable: noteable, project: project, note: note_text) }
let_it_be(:note) { build(:note, noteable: noteable, project: project, note: note_text) }
let_it_be(:children) { [child, second_child] }
shared_examples 'adds child work items' do
@ -423,7 +423,7 @@ RSpec.describe Notes::QuickActionsService, feature_category: :team_planning do
let_it_be_with_reload(:noteable) { create(:work_item, :objective, project: project) }
let_it_be_with_reload(:child) { create(:work_item, :objective, project: project) }
let_it_be(:note_text) { "/remove_child #{child.to_reference}" }
let_it_be(:note) { create(:note, noteable: noteable, project: project, note: note_text) }
let_it_be(:note) { build(:note, noteable: noteable, project: project, note: note_text) }
before do
create(:parent_link, work_item_parent: noteable, work_item: child)
@ -465,7 +465,7 @@ RSpec.describe Notes::QuickActionsService, feature_category: :team_planning do
let_it_be_with_reload(:noteable) { create(:work_item, :objective, project: project) }
let_it_be_with_reload(:parent) { create(:work_item, :objective, project: project) }
let_it_be(:note_text) { "/set_parent #{parent.to_reference}" }
let_it_be(:note) { create(:note, noteable: noteable, project: project, note: note_text) }
let_it_be(:note) { build(:note, noteable: noteable, project: project, note: note_text) }
shared_examples 'sets work item parent' do
it 'leaves the note empty' do
@ -536,7 +536,7 @@ RSpec.describe Notes::QuickActionsService, feature_category: :team_planning do
context 'when user is not allowed to promote work item' do
let_it_be_with_reload(:noteable) { create(:work_item, :task, project: project) }
let_it_be(:note_text) { '/promote_to issue' }
let_it_be(:note) { create(:note, noteable: noteable, project: project, note: note_text) }
let_it_be(:note) { build(:note, noteable: noteable, project: project, note: note_text) }
before do
project.team.find_member(maintainer.id).destroy!
@ -551,7 +551,7 @@ RSpec.describe Notes::QuickActionsService, feature_category: :team_planning do
context 'on a task' do
let_it_be_with_reload(:noteable) { create(:work_item, :task, project: project) }
let_it_be(:note_text) { '/promote_to Issue' }
let_it_be(:note) { create(:note, noteable: noteable, project: project, note: note_text) }
let_it_be(:note) { build(:note, noteable: noteable, project: project, note: note_text) }
it_behaves_like 'promotes work item', from: 'task', to: 'issue'
@ -565,7 +565,7 @@ RSpec.describe Notes::QuickActionsService, feature_category: :team_planning do
context 'on an issue' do
let_it_be_with_reload(:noteable) { create(:work_item, :issue, project: project) }
let_it_be(:note_text) { '/promote_to Incident' }
let_it_be(:note) { create(:note, noteable: noteable, project: project, note: note_text) }
let_it_be(:note) { build(:note, noteable: noteable, project: project, note: note_text) }
it_behaves_like 'promotes work item', from: 'issue', to: 'incident'
@ -576,6 +576,38 @@ RSpec.describe Notes::QuickActionsService, feature_category: :team_planning do
end
end
end
context 'when existing note contains quick actions' do
let(:note_text) { "foo\n/close\nbar" }
before do
note.save!
note.note = edit_note_text
end
context 'when a quick action exists in original note' do
let(:edit_note_text) { "foo\n/close\nbar\nbaz" }
it 'sanitizes/removes any quick actions and does not execute them' do
content = execute(note)
expect(content).to eq "foo\nbar\nbaz"
expect(note.noteable.open?).to be_truthy
end
end
context 'when a new quick action is used in new note' do
let(:edit_note_text) { "bar\n/react :smile:\nfoo" }
it 'executes any quick actions not in unedited note' do
content = execute(note)
expect(content).to eq "bar\nfoo"
expect(note.noteable.award_emoji.first.name).to eq 'smile'
expect(note.noteable.open?).to be_truthy
end
end
end
end
describe '.supported?' do

View File

@ -135,6 +135,35 @@ RSpec.describe Notes::UpdateService, feature_category: :team_planning do
])
end
end
context 'when existing note contains quick actions' do
let!(:note) { create(:note, project: project, noteable: issue, author: user2, note: "foo\n/close\nbar") }
before do
update_note(edit_note_text)
note.reload
note.noteable.reload
end
context 'when a quick action exists in original note' do
let(:edit_note_text) { { note: "foo\n/close\nbar\nbaz" } }
it 'sanitizes/removes any quick actions and does not execute them' do
expect(note.note).to eq "foo\nbar\nbaz"
expect(note.noteable.open?).to be_truthy
end
end
context 'when a new quick action is used in new note' do
let(:edit_note_text) { { note: "bar\n/react :smile:\nfoo" } }
it 'executes any quick actions not in unedited note' do
expect(note.note).to eq "bar\nfoo"
expect(note.noteable.award_emoji.first.name).to eq 'smile'
expect(note.noteable.open?).to be_truthy
end
end
end
end
context 'when note text was not changed' do

View File

@ -0,0 +1,124 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Packages::Npm::CheckManifestCoherenceService, :aggregate_failures, feature_category: :package_registry do
let_it_be(:package) { build(:npm_package) }
let_it_be(:package_metadata) { build(:npm_metadatum, package: package) }
let(:tar_header) { Gem::Package::TarHeader.new(name: 'json', size: package_json.size, mode: 0o644, prefix: '') }
let(:package_json_entry) { Gem::Package::TarReader::Entry.new(tar_header, StringIO.new(package_json)) }
let(:service) { described_class.new(package, package_json_entry) }
subject(:execute_service) { service.execute }
describe '#execute' do
using RSpec::Parameterized::TableSyntax
let(:package_name) { package.name }
let(:package_version) { package.version }
let(:package_scripts) { package_metadata.package_json_scripts }
where(:name, :version, :scripts, :coherent) do
ref(:package_name) | ref(:package_version) | ref(:package_scripts) | true
'foo' | ref(:package_version) | ref(:package_scripts) | false
ref(:package_name) | '5.0.3' | ref(:package_scripts) | false
ref(:package_name) | ref(:package_version) | { test: 'different script' } | false
'foo' | '5.0.3' | { test: 'different script' } | false
end
with_them do
let(:package_json) do
{
name: name,
version: version,
scripts: scripts
}.to_json
end
if params[:coherent]
it { is_expected.to be_success }
else
it 'raises a mismatch error' do
expect { execute_service }
.to raise_error(described_class::MismatchError, 'Package manifest is not coherent')
end
end
end
context 'when the package metadata is missing' do
let(:package_json) { { name: package_name, version: package_version, scripts: {} }.to_json }
before do
package.npm_metadatum = nil
end
it { is_expected.to be_success }
end
end
describe 'SajHandler' do
let(:handler) { described_class::SajHandler.new }
describe 'parsing a json document' do
let(:json) { { name: 'test', version: '1.2.3', scripts: { test: 'echo "test"' } }.to_json }
subject(:parse) { ::Oj.saj_parse(handler, json) }
it 'extracts the fields' do
expect { parse }.to raise_error(described_class::SajHandler::ParsingDoneError)
expect(handler.name).to eq('test')
expect(handler.version).to eq('1.2.3')
expect(handler.scripts).to eq('test' => 'echo "test"')
end
context 'with a different fields order' do
let(:json) { { scripts: { test: 'echo "test"' }, name: 'test', version: '1.2.3' }.to_json }
it 'extracts the fields' do
expect { parse }.to raise_error(described_class::SajHandler::ParsingDoneError)
expect(handler.name).to eq('test')
expect(handler.version).to eq('1.2.3')
expect(handler.scripts).to eq('test' => 'echo "test"')
end
end
context 'with no scripts field' do
let(:json) { { name: 'test', version: '1.2.3' }.to_json }
it 'extracts the name and version fields' do
expect { parse }.not_to raise_error
expect(handler.name).to eq('test')
expect(handler.version).to eq('1.2.3')
expect(handler.scripts).to eq({})
end
end
context 'with very large fields' do
let(:json) do
{
name: 'test',
version: '1.2.3',
scripts: { test: 'echo "test"' },
extra: 'test' * 10000,
another_hash: { large_field: 'aaaa' * 10000 }
}.to_json
end
it 'avoids extract large fields' do
expect(handler).to receive(:hash_start).twice.and_call_original
expect(handler).to receive(:hash_end).once.and_call_original
expect(handler).to receive(:add_value).exactly(3).times.and_call_original
expect { parse }.to raise_error(described_class::SajHandler::ParsingDoneError)
expect(handler.name).to eq('test')
expect(handler.version).to eq('1.2.3')
expect(handler.scripts).to eq('test' => 'echo "test"')
end
end
end
end
end

View File

@ -20,6 +20,10 @@ RSpec.describe ::Packages::Npm::ProcessPackageFileService, feature_category: :pa
package.project_id,
package.name
)
expect_next_instance_of(::Packages::Npm::CheckManifestCoherenceService, package,
instance_of(Gem::Package::TarReader::Entry)) do |service|
expect(service).to receive(:execute)
end
expect(package).to receive(:default!)
service.execute

View File

@ -707,18 +707,18 @@ RSpec.describe QuickActions::InterpretService, feature_category: :team_planning
end
shared_examples 'shrug command' do
it 'appends ¯\_(ツ)_/¯ to the comment' do
it 'adds ¯\_(ツ)_/¯' do
new_content, _, _ = service.execute(content, issuable)
expect(new_content).to end_with(described_class::SHRUG)
expect(new_content).to eq(described_class::SHRUG)
end
end
shared_examples 'tableflip command' do
it 'appends (╯°□°)╯︵ ┻━┻ to the comment' do
it 'adds (╯°□°)╯︵ ┻━┻' do
new_content, _, _ = service.execute(content, issuable)
expect(new_content).to end_with(described_class::TABLEFLIP)
expect(new_content).to eq(described_class::TABLEFLIP)
end
end
@ -2204,7 +2204,7 @@ RSpec.describe QuickActions::InterpretService, feature_category: :team_planning
text, commands = service.execute(content, issue, only: [:shrug])
expect(commands).to be_empty
expect(text).to eq("test #{described_class::SHRUG}\n/close")
expect(text).to eq("#{described_class::SHRUG}\n/close")
end
it 'preserves leading whitespace' do

View File

@ -56,7 +56,7 @@ RSpec.describe WorkItems::CreateService, feature_category: :team_planning do
it 'saves the work item and applies the quick action' do
expect(service_result).to be_success
expect(work_item).to be_persisted
expect(work_item.description).to eq(' ¯\_(ツ)_/¯')
expect(work_item.description).to eq('¯\_(ツ)_/¯')
end
end
end

View File

@ -87,7 +87,78 @@ RSpec.describe WorkItems::UpdateService, feature_category: :team_planning do
it 'applies the quick action' do
expect do
update_work_item
end.to change(work_item, :description).to(' ¯\_(ツ)_/¯')
end.to change(work_item, :description).to('¯\_(ツ)_/¯')
end
end
it_behaves_like 'issuable record that supports quick actions' do
let(:opts) { params }
let(:current_user) { user }
let(:work_item) { create(:work_item, project: project, description: "some random description") }
let(:issuable) { update_work_item[:work_item] }
end
it_behaves_like 'issuable record that supports quick actions', with_widgets: true do
let(:opts) { params }
let(:current_user) { user }
let(:work_item) { create(:work_item, project: project, description: "some random description") }
let(:issuable) { update_work_item[:work_item] }
end
it_behaves_like 'issuable record does not run quick actions when not editing description' do
let(:label) { create(:label, project: project) }
let(:assignee) { create(:user, maintainer_of: project) }
let(:work_item) { create(:work_item, project: project, description: old_description) }
let(:opts) { params }
let(:updated_issuable) { update_work_item[:work_item] }
end
it_behaves_like 'issuable record does not run quick actions when not editing description', with_widgets: true do
let(:label) { create(:label, project: project) }
let(:assignee) { create(:user, maintainer_of: project) }
let(:work_item) { create(:work_item, project: project, description: old_description) }
let(:opts) { params }
let(:updated_issuable) { update_work_item[:work_item] }
end
context 'when work item type is not default issue' do
# when quick actions are passed in `description` param those are not interpreted and just saved into description
# as plain text
#
# it_behaves_like 'issuable record that does not supports quick actions' do
# let(:opts) { params }
# let(:current_user) { user }
# let(:work_item) { create(:work_item, :task, project: project, description: "some random description") }
# let(:issuable) { update_work_item[:work_item] }
# end
it_behaves_like 'issuable record that supports quick actions', with_widgets: true do
let(:opts) { params }
let(:current_user) { user }
let(:work_item) { create(:work_item, :task, project: project, description: "some random description") }
let(:issuable) { update_work_item[:work_item] }
end
end
context 'when work item labels widget is disabled' do
before do
widget_definitions = WorkItems::Type.default_by_type(:issue).widget_definitions
widget_definitions.find_by_widget_type(:labels).update!(disabled: true)
widget_definitions.find_by_widget_type(:assignees).update!(disabled: true)
end
it_behaves_like 'issuable record that does not supports quick actions' do
let(:opts) { params }
let(:current_user) { user }
let(:work_item) { create(:work_item, project: project, description: "some random description") }
let(:issuable) { update_work_item[:work_item] }
end
it_behaves_like 'issuable record that does not supports quick actions', with_widgets: true do
let(:opts) { params }
let(:current_user) { user }
let(:work_item) { create(:work_item, project: project, description: "some random description") }
let(:issuable) { update_work_item[:work_item] }
end
end
end
@ -172,7 +243,7 @@ RSpec.describe WorkItems::UpdateService, feature_category: :team_planning do
end
end
context 'when decription is changed' do
context 'when description is changed' do
let(:opts) { { description: 'description changed' } }
include_examples 'publish WorkItems::WorkItemUpdatedEvent event',
@ -197,7 +268,7 @@ RSpec.describe WorkItems::UpdateService, feature_category: :team_planning do
end
end
context 'when decription is not changed' do
context 'when description is not changed' do
let(:opts) { { title: 'title changed' } }
it 'does not trigger GraphQL description updated subscription' do

View File

@ -67,7 +67,7 @@ RSpec.shared_examples 'update work item description widget' do
it_behaves_like 'quick action is applied' do
let(:new_description) { "/tableflip updated description\n/shrug\n/cc @#{developer.username}" }
# note: \cc performs no action since 15.0
let(:filtered_description) { "updated description (╯°□°)╯︵ ┻━┻\n ¯\\_(ツ)_\n/cc @#{developer.username}" }
let(:filtered_description) { "(╯°□°)╯︵ ┻━┻\n¯\\_(ツ)_\n/cc @#{developer.username}" }
let(:expected_response) do
{
'widgets' => include({

View File

@ -5,15 +5,33 @@ RSpec.shared_examples 'search results filtered by labels' do
let_it_be(:labeled_issue) { create(:labeled_issue, labels: [project_label], project: project, title: 'foo project') }
let_it_be(:unlabeled_issue) { create(:issue, project: project, title: 'foo unlabeled') }
let(:filters) { { labels: [project_label.id] } }
before do
::Elastic::ProcessBookkeepingService.track!(labeled_issue)
::Elastic::ProcessBookkeepingService.track!(unlabeled_issue)
ensure_elasticsearch_index!
end
it 'filters by labels', :sidekiq_inline do
expect(results.objects(scope)).to contain_exactly(labeled_issue)
context 'when labels filter is provided' do
let(:filters) { { labels: [project_label.id] } }
it 'filters by labels', :sidekiq_inline do
expect(results.objects(scope)).to contain_exactly(labeled_issue)
end
end
context 'when label_name filter is provided' do
let(:filters) { { label_name: [project_label.name] } }
it 'filters by labels', :sidekiq_inline do
expect(results.objects(scope)).to contain_exactly(labeled_issue)
end
end
context 'when both labels and label_name filters are provided' do
let(:filters) { { labels: [0], label_name: [project_label.name] } }
it 'uses label_name filter and filters by labels', :sidekiq_inline do
expect(results.objects(scope)).to contain_exactly(labeled_issue)
end
end
end

View File

@ -218,13 +218,13 @@ RSpec.shared_examples 'issuable quick actions' do
QuickAction.new(
action_text: "/shrug oops",
expectation: ->(noteable, can_use_quick_action) {
expect(noteable.notes&.last&.note == "HELLO\noops ¯\\_(ツ)_\nWORLD").to eq(can_use_quick_action)
expect(noteable.notes&.last&.note == "HELLO\n¯\\_(ツ)_\nWORLD").to eq(can_use_quick_action)
}
),
QuickAction.new(
action_text: "/tableflip oops",
expectation: ->(noteable, can_use_quick_action) {
expect(noteable.notes&.last&.note == "HELLO\noops (╯°□°)╯︵ ┻━┻\nWORLD").to eq(can_use_quick_action)
expect(noteable.notes&.last&.note == "HELLO\n(╯°□°)╯︵ ┻━┻\nWORLD").to eq(can_use_quick_action)
}
),
QuickAction.new(

View File

@ -3,15 +3,19 @@
# Specifications for behavior common to all objects with executable attributes.
# It can take a `default_params`.
RSpec.shared_examples 'issuable record that supports quick actions' do
RSpec.shared_examples 'issuable record that does not supports quick actions' do |with_widgets: false|
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user, maintainer_of: project) }
let_it_be(:assignee) { create(:user, maintainer_of: project) }
let_it_be(:milestone) { create(:milestone, project: project) }
let_it_be(:labels) { create_list(:label, 3, project: project) }
let(:new_descr) { "some updated description" }
let(:base_params) { { title: 'My issuable title' } }
let(:params) { base_params.merge(defined?(default_params) ? default_params : {}).merge(example_params) }
let(:params) { base_params.merge(with_widgets ? { label_ids: example_params.delete(:label_ids) } : example_params) }
let(:widget_params) do
with_widgets ? { description_widget: { description: example_params.delete(:description) } } : {}
end
before do
issuable.reload
@ -20,12 +24,13 @@ RSpec.shared_examples 'issuable record that supports quick actions' do
context 'with labels in command only' do
let(:example_params) do
{
description: "/label ~#{labels.first.name} ~#{labels.second.name}\n/unlabel ~#{labels.third.name}"
description: "#{new_descr}\n/label ~#{labels.first.name} ~#{labels.second.name}\n/unlabel ~#{labels.third.name}"
}
end
it 'attaches labels to issuable' do
expect(issuable.label_ids).to match_array([labels.first.id, labels.second.id])
expect(issuable.label_ids).to be_empty
expect(issuable.description).to eq new_descr
end
end
@ -33,25 +38,159 @@ RSpec.shared_examples 'issuable record that supports quick actions' do
let(:example_params) do
{
label_ids: [labels.second.id],
description: "/label ~#{labels.first.name}\n/unlabel ~#{labels.third.name}"
description: "#{new_descr}\n/label ~#{labels.first.name}\n/unlabel ~#{labels.third.name}"
}
end
it 'attaches all labels to issuable' do
expect(issuable.label_ids).to match_array([labels.first.id, labels.second.id])
expect(issuable.label_ids).to match_array([labels.second.id])
expect(issuable.description).to eq new_descr
end
end
context 'with assignee and milestone in command only' do
let(:example_params) do
{
description: %(/assign @#{assignee.username}\n/milestone %"#{milestone.name}")
description: %(#{new_descr}\n/assign @#{assignee.username}\n/milestone %"#{milestone.name}")
}
end
it 'assigns and sets milestone to issuable' do
expect(issuable.assignees).to be_empty
expect(issuable.milestone).to be_nil
expect(issuable.description).to eq new_descr
end
end
end
RSpec.shared_examples 'issuable record that supports quick actions' do |with_widgets: false|
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user, maintainer_of: project) }
let_it_be(:assignee) { create(:user, maintainer_of: project) }
let_it_be(:milestone) { create(:milestone, project: project) }
let_it_be(:labels) { create_list(:label, 3, project: project) }
let(:new_descr) { "some updated description" }
let(:base_params) { { title: 'My issuable title' } }
let(:params) { base_params.merge(with_widgets ? { label_ids: example_params.delete(:label_ids) } : example_params) }
let(:widget_params) do
with_widgets ? { description_widget: { description: example_params.delete(:description) } } : {}
end
before do
issuable.reload
end
context 'with labels in command only' do
let(:example_params) do
{
description: "#{new_descr}\n/label ~#{labels.first.name} ~#{labels.second.name}\n/unlabel ~#{labels.third.name}"
}
end
it 'attaches labels to issuable' do
expect(issuable.label_ids).to match_array([labels.first.id, labels.second.id])
expect(issuable.description).to eq new_descr
end
end
context 'with labels in params and command' do
let(:example_params) do
{
label_ids: [labels.second.id],
description: "#{new_descr}\n/label ~#{labels.first.name}\n/unlabel ~#{labels.third.name}"
}
end
it 'attaches all labels to issuable' do
expect(issuable.label_ids).to match_array([labels.first.id, labels.second.id])
expect(issuable.description).to eq new_descr
end
end
context 'with assignee and milestone in command only' do
let(:example_params) do
{
description: %(#{new_descr}\n/assign @#{assignee.username}\n/milestone %"#{milestone.name}")
}
end
it 'assigns and sets milestone to issuable' do
expect(issuable.assignees).to eq([assignee])
expect(issuable.milestone).to eq(milestone)
expect(issuable.description).to eq new_descr
# WorkItem milestone widget does not support quick the action yet
expect(issuable.milestone).to eq(milestone) unless issuable.is_a?(WorkItem)
expect(issuable.milestone).to be_nil if issuable.is_a?(WorkItem)
end
end
end
RSpec.shared_examples 'issuable record does not run quick actions when not editing description' do |with_widgets: false|
let(:residual_quick_actions) { "/label ~#{label.name}\n/assign @#{assignee.username}" }
let(:old_description) { "foo\n#{residual_quick_actions}\nbar" }
let(:base_params) { { title: 'My issuable title' } }
let(:params) { base_params.merge(with_widgets ? {} : description_param) }
let(:widget_params) { with_widgets ? { description_widget: description_param } : {} }
before do
updated_issuable.reload
end
context 'when no description param is provided' do
let(:description_param) { {} }
it 'sanitizes/removes any residual quick actions and does not execute them' do
expect(updated_issuable.description).to eq "foo\nbar"
expect(updated_issuable.labels).to be_empty
expect(updated_issuable.assignees).to be_empty
end
end
context 'when description param is provided' do
let(:description_param) { { description: "bar\n/react :smile:\nfoo" } }
it 'executes only quick actions provided in the description param and skips residual quick actions' do
expect(updated_issuable.description).to eq "bar\nfoo"
expect(updated_issuable.award_emoji.first.name).to eq 'smile'
expect(updated_issuable.labels).to be_empty
expect(updated_issuable.assignees).to be_empty
end
end
context 'when original description is replaced by description containing a residual quick action' do
let(:description_param) do
{ description: "bar\n/react :smile:\n#{residual_quick_actions}\nfoo" }
end
# side-effect of not executing the residual quick actions resulting in a quick action not being executed
# even if provided by the user when editing the description
it 'executes only the non residual quick actions even though provided in description param' do
expect(updated_issuable.description).to eq "bar\nfoo"
expect(updated_issuable.award_emoji.first.name).to eq 'smile'
expect(updated_issuable.labels).to be_empty
expect(updated_issuable.assignees).to be_empty
end
end
context 'when prepending description with new content' do
let(:description_param) { { description: "bar\n/react :smile:\nfoo\n\n#{old_description}" } }
it 'executes only the non residual quick actions' do
expect(updated_issuable.description).to eq "bar\nfoo\n\nfoo\nbar"
expect(updated_issuable.award_emoji.first.name).to eq 'smile'
expect(updated_issuable.labels).to be_empty
expect(updated_issuable.assignees).to be_empty
end
end
context 'when appending description with new content' do
let(:description_param) { { description: "#{old_description}\n\nbar\n/react :smile:\nfoo" } }
it 'executes only the non residual quick actions' do
expect(updated_issuable.description).to eq "foo\nbar\n\nbar\nfoo"
expect(updated_issuable.award_emoji.first.name).to eq 'smile'
expect(updated_issuable.labels).to be_empty
expect(updated_issuable.assignees).to be_empty
end
end
end

View File

@ -0,0 +1,91 @@
# frozen_string_literal: true
require 'spec_helper'
require_relative '../../../../lib/tasks/gitlab/tokens/manage_expiry_task'
RSpec.describe 'Tasks::Gitlab::Tokens::ManageExpiryTask', feature_category: :system_access do
# rubocop:disable RSpec/AvoidTestProf -- this is not a migration spec
let_it_be(:expires_at) { Date.today + 364.days }
let_it_be(:user) { create(:user) }
let_it_be(:migration_status) do
create(:batched_background_migration, :finished,
job_class_name: 'CleanupPersonalAccessTokensWithNilExpiresAt',
table_name: 'personal_access_tokens',
column_name: 'id')
end
# rubocop:enable RSpec/AvoidTestProf
let!(:personal_access_token1) { create(:personal_access_token, user: user, expires_at: expires_at) }
let!(:personal_access_token2) { create(:personal_access_token, user: user, expires_at: expires_at) }
let!(:personal_access_token3) { create(:personal_access_token, user: user, expires_at: expires_at + 1.day) }
subject(:task) { Tasks::Gitlab::Tokens::ManageExpiryTask.new }
describe '.analyze' do
it 'calls the expected methods' do
expect(task).to receive(:show_pat_expires_at_migration_status)
expect(task).to receive(:show_most_common_pat_expiration_dates)
task.analyze
end
end
describe '.edit' do
it 'calls analyze and prompts for action' do
expect(task).to receive(:analyze).at_least(:once)
expect(task).to receive(:prompt_action).at_least(:once).and_return(false)
task.edit
end
end
describe '.show_pat_expires_at_migration_status' do
it 'prints the migration status' do
expect { task.send(:show_pat_expires_at_migration_status) }.to output(
/Started at: #{migration_status[:started_at]}\nFinished : #{migration_status[:finished_at]}/).to_stdout
end
end
describe '.show_most_common_pat_expiration_dates' do
let(:second) { personal_access_token3.expires_at }
it 'shows the two groups of expiration dates' do
expect { task.send(:show_most_common_pat_expiration_dates) }.to output(
/#{expires_at}.*\|\s+2\s+\|\n\|\s+#{second}\s+\|\s+1\s+/).to_stdout
end
end
describe '.extend_expiration_date' do
it 'extends the expiration date for selected tokens' do
new_date = expires_at + 1.day
prompt = instance_double(TTY::Prompt)
allow(task).to receive(:prompt_expiration_date_selection).and_return(expires_at)
allow(TTY::Prompt).to receive(:new).and_return(prompt)
allow(prompt).to receive(:ask).and_return(new_date.to_s)
allow(prompt).to receive(:yes?).and_return(true)
expect(task).to receive(:update_tokens_with_expiration).with(expires_at, new_date).and_call_original
expect { task.send(:extend_expiration_date) }.to output(/Updated 2 tokens!/).to_stdout
expect(personal_access_token1.reload.expires_at).to eq(new_date)
expect(personal_access_token2.reload.expires_at).to eq(new_date)
end
end
describe '.remove_expiration_date' do
it 'removes the expiration date for selected tokens' do
prompt = instance_double(TTY::Prompt)
allow(task).to receive(:prompt_expiration_date_selection).and_return(expires_at)
allow(TTY::Prompt).to receive(:new).and_return(prompt)
allow(prompt).to receive(:yes?).and_return(true)
expect(task).to receive(:update_tokens_with_expiration).with(expires_at, nil).and_call_original
expect { task.send(:remove_expiration_date) }.to output(/Updated 2 tokens!/).to_stdout
expect(personal_access_token1.reload.expires_at).to be_nil
expect(personal_access_token2.reload.expires_at).to be_nil
end
end
end

View File

@ -26,7 +26,7 @@ RSpec.describe Packages::Npm::ProcessPackageFileWorker, type: :worker, feature_c
it 'does not call the service' do
expect(Packages::Npm::ProcessPackageFileService).not_to receive(:new)
worker.perform(-1)
worker.perform(non_existing_record_id)
end
end
@ -47,6 +47,30 @@ RSpec.describe Packages::Npm::ProcessPackageFileWorker, type: :worker, feature_c
worker.perform(package_file.id)
end
context 'with manefist coherence mismatch error' do
let(:exception) do
Packages::Npm::CheckManifestCoherenceService::MismatchError.new('Package manifest is not coherent')
end
before do
allow_next_instance_of(Packages::Npm::ProcessPackageFileService, package_file) do |service|
allow(service).to receive(:execute).and_raise(exception)
end
end
it 'calls the error handling service & sets the package status to error' do
expect(worker).to receive(:process_package_file_error).with(
package_file: package_file,
exception: exception
).and_call_original
worker.perform(package_file.id)
expect(package_file.package.reset).to be_error
expect(package_file.package.status_message).to eq('Package manifest is not coherent')
end
end
end
end
end

View File

@ -9,6 +9,7 @@ NUMBER_OF_WORKERS = ENV['NUMBER_OF_WORKERS'] || 10
NUMBER_OF_JOBS = ENV['NUMBER_OF_JOBS'] || 1000
NUMBER_OF_DUPLICATE_JOBS_ALLOWED = ENV['NUMBER_OF_DUPLICATE_JOBS_ALLOWED'] || 10
JOB_FETCHER = (ENV['JOB_FETCHER'] || :semi).to_sym # :basic, :semi, :reliable
NUMBER_OF_JOBS_LOST_ALLOWED = ENV['NUMBER_OF_JOBS_LOST_ALLOWED'] || (JOB_FETCHER == :reliable ? 0 : 3)
TEST_CLEANUP_INTERVAL = 20
TEST_LEASE_INTERVAL = 5
WAIT_CLEANUP = TEST_CLEANUP_INTERVAL +

View File

@ -105,10 +105,10 @@ Sidekiq.redis do |redis|
end
end
puts "Remaining unprocessed: #{jobs_lost}"
puts "Remaining unprocessed: #{jobs_lost}. Max allowed: #{NUMBER_OF_JOBS_LOST_ALLOWED}"
puts "Duplicates found: #{duplicates}. Max allowed: #{NUMBER_OF_DUPLICATE_JOBS_ALLOWED}"
if jobs_lost.zero? && duplicates <= NUMBER_OF_DUPLICATE_JOBS_ALLOWED
if jobs_lost <= NUMBER_OF_JOBS_LOST_ALLOWED && duplicates <= NUMBER_OF_DUPLICATE_JOBS_ALLOWED
exit 0
else
exit 1