Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-06-08 12:08:54 +00:00
parent dca8df0c90
commit 473b876fe3
73 changed files with 961 additions and 140 deletions

View File

@ -72,6 +72,7 @@ db:check-schema-single-db:
db:check-migrations:
extends:
- .db-job-base
- .use-pg13 # Should match the db same version used by GDK
- .rails:rules:ee-and-foss-mr-with-migration
script:
- git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME:$CI_MERGE_REQUEST_TARGET_BRANCH_NAME --depth 20

View File

@ -336,13 +336,11 @@ RSpec/FactoryBot/AvoidCreate:
- 'spec/helpers/wiki_helper_spec.rb'
- 'spec/helpers/wiki_page_version_helper_spec.rb'
- 'spec/lib/sidebars/admin/menus/abuse_reports_menu_spec.rb'
- 'spec/lib/sidebars/admin/menus/monitoring_menu_spec.rb'
- 'spec/lib/sidebars/groups/menus/ci_cd_menu_spec.rb'
- 'spec/lib/sidebars/groups/menus/group_information_menu_spec.rb'
- 'spec/lib/sidebars/groups/menus/issues_menu_spec.rb'
- 'spec/lib/sidebars/groups/menus/kubernetes_menu_spec.rb'
- 'spec/lib/sidebars/groups/menus/merge_requests_menu_spec.rb'
- 'spec/lib/sidebars/groups/menus/observability_menu_spec.rb'
- 'spec/lib/sidebars/groups/menus/packages_registries_menu_spec.rb'
- 'spec/lib/sidebars/groups/menus/settings_menu_spec.rb'
- 'spec/lib/sidebars/groups/super_sidebar_panel_spec.rb'
@ -358,17 +356,8 @@ RSpec/FactoryBot/AvoidCreate:
- 'spec/lib/sidebars/projects/menus/project_information_menu_spec.rb'
- 'spec/lib/sidebars/projects/menus/repository_menu_spec.rb'
- 'spec/lib/sidebars/projects/menus/security_compliance_menu_spec.rb'
- 'spec/lib/sidebars/projects/menus/settings_menu_spec.rb'
- 'spec/lib/sidebars/projects/menus/shimo_menu_spec.rb'
- 'spec/lib/sidebars/projects/panel_spec.rb'
- 'spec/lib/sidebars/projects/super_sidebar_panel_spec.rb'
- 'spec/lib/sidebars/search/panel_spec.rb'
- 'spec/lib/sidebars/user_profile/panel_spec.rb'
- 'spec/lib/sidebars/user_settings/panel_spec.rb'
- 'spec/lib/sidebars/your_work/menus/issues_menu_spec.rb'
- 'spec/lib/sidebars/your_work/menus/merge_requests_menu_spec.rb'
- 'spec/lib/sidebars/your_work/menus/todos_menu_spec.rb'
- 'spec/lib/sidebars/your_work/panel_spec.rb'
- 'spec/mailers/abuse_report_mailer_spec.rb'
- 'spec/mailers/devise_mailer_spec.rb'
- 'spec/mailers/emails/auto_devops_spec.rb'

View File

@ -2,6 +2,12 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 16.0.4 (2023-06-08)
### Fixed (1 change)
- [Fix LDAP tls_options not working](gitlab-org/gitlab@e6038d0d4e8bb190ccfeca5fe7204d6a6af266e5) ([merge request](gitlab-org/gitlab!122797))
## 16.0.3 (2023-06-06)
### Fixed (3 changes)

View File

@ -1 +1 @@
1934b9991139b48ed58d78dc89b35c262acd5150
468ba7de9380a1eb6321dbdf9b7ddffd7eda90f7

View File

@ -34,7 +34,7 @@ export default {
<template>
<button
type="button"
class="context-switcher-toggle gl-p-0 gl-bg-transparent gl-hover-bg-t-gray-a-08 gl-focus-bg-t-gray-a-08 gl-border-0 border-top border-bottom gl-border-gray-a-08 gl-box-shadow-none gl-display-flex gl-align-items-center gl-font-weight-bold gl-w-full gl-h-8 gl-flex-shrink-0"
class="context-switcher-toggle gl-p-0 gl-bg-transparent gl-hover-bg-t-gray-a-08 gl-focus-bg-t-gray-a-08 gl-border-0 border-top border-bottom gl-border-gray-a-08! gl-box-shadow-none gl-display-flex gl-align-items-center gl-font-weight-bold gl-w-full gl-h-8 gl-flex-shrink-0"
data-qa-selector="context_switcher"
>
<span

View File

@ -15,6 +15,55 @@ module Admin
def project_missing_pipeline_yaml?(project)
project.repository&.gitlab_ci_yml.blank?
end
def code_suggestions_token_explanation
link_start = code_suggestions_link_start(code_suggestions_pat_docs_url)
# rubocop:disable Layout/LineLength
# rubocop:disable Style/FormatString
s_('CodeSuggestionsSM|Your personal access token from GitLab.com. See the %{link_start}documentation%{link_end} for information on creating a personal access token.')
.html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
# rubocop:enable Style/FormatString
# rubocop:enable Layout/LineLength
end
def code_suggestions_agreement
terms_link_start = code_suggestions_link_start(code_suggestions_agreement_url)
ai_docs_link_start = code_suggestions_link_start(code_suggestions_ai_docs_url)
# rubocop:disable Layout/LineLength
# rubocop:disable Style/FormatString
s_('CodeSuggestionsSM|&#8226; Agree to the %{terms_link_start}GitLab Testing Agreement%{link_end}.%{br} &#8226; Acknowledge that GitLab will send data from the instance, including personal data, to Google for cloud hosting.%{br} &nbsp;&nbsp;&nbsp;We may also send data to %{ai_docs_link_start}third-party AI providers%{link_end} to provide this feature.')
.html_safe % { terms_link_start: terms_link_start, ai_docs_link_start: ai_docs_link_start, link_end: '</a>'.html_safe, br: '</br>'.html_safe }
# rubocop:enable Style/FormatString
# rubocop:enable Layout/LineLength
end
private
# rubocop:disable Gitlab/DocUrl
# We want to link SaaS docs for flexibility for every URL related to Code Suggestions on Self Managed.
# We expect to update docs often during the Beta and we want to point user to the most up to date information.
def code_suggestions_docs_url
'https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html'
end
def code_suggestions_agreement_url
'https://about.gitlab.com/handbook/legal/testing-agreement/'
end
def code_suggestions_ai_docs_url
'https://docs.gitlab.com/ee/user/ai_features.html'
end
def code_suggestions_pat_docs_url
'https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token'
end
# rubocop:enable Gitlab/DocUrl
def code_suggestions_link_start(url)
"<a href=\"#{url}\" target=\"_blank\" rel=\"noopener noreferrer\">".html_safe
end
end
end
end

View File

@ -218,6 +218,7 @@ module ApplicationSettingsHelper
:admin_mode,
:after_sign_out_path,
:after_sign_up_text,
:ai_access_token,
:akismet_api_key,
:akismet_enabled,
:allow_local_requests_from_hooks_and_services,
@ -309,6 +310,7 @@ module ApplicationSettingsHelper
:inactive_projects_delete_after_months,
:inactive_projects_min_size_mb,
:inactive_projects_send_warning_email_after_months,
:instance_level_code_suggestions_enabled,
:invisible_captcha_enabled,
:jira_connect_application_key,
:jira_connect_public_key_storage_enabled,

View File

@ -720,6 +720,10 @@ class ApplicationSetting < MainClusterwide::ApplicationRecord
allow_nil: false,
inclusion: { in: [true, false], message: N_('must be a boolean value') }
validates :ai_access_token,
presence: { message: N_("is required to enable Code Suggestions") },
if: :instance_level_code_suggestions_enabled
attr_encrypted :asset_proxy_secret_key,
mode: :per_attribute_iv,
key: Settings.attr_encrypted_db_key_base_truncated,
@ -948,4 +952,5 @@ class ApplicationSetting < MainClusterwide::ApplicationRecord
end
end
ApplicationSetting.prepend(ApplicationSettingMaskedAttrs)
ApplicationSetting.prepend_mod_with('ApplicationSetting')

View File

@ -37,6 +37,7 @@ module ApplicationSettingImplementation
{
admin_mode: false,
after_sign_up_text: nil,
ai_access_token: nil,
akismet_enabled: false,
akismet_api_key: nil,
allow_local_requests_from_system_hooks: true,
@ -104,6 +105,7 @@ module ApplicationSettingImplementation
housekeeping_gc_period: 200,
housekeeping_incremental_repack_period: 10,
import_sources: Settings.gitlab['import_sources'],
instance_level_code_suggestions_enabled: false,
invisible_captcha_enabled: false,
issues_create_limit: 300,
jira_connect_application_key: nil,

View File

@ -0,0 +1,14 @@
# frozen_string_literal: true
# Similar to MASK_PASSWORD mechanism we do for EE, see:
# https://gitlab.com/gitlab-org/gitlab/-/blob/463bb1f855d71fadef931bd50f1692ee04f211a8/ee/app/models/ee/application_setting.rb#L15
# but for non-EE attributes.
module ApplicationSettingMaskedAttrs
MASK = '*****'
def ai_access_token=(value)
return if value == MASK
super
end
end

View File

@ -11,9 +11,14 @@ module AutoMerge
end
def process(merge_request)
logger.info("Processing Automerge")
return unless merge_request.actual_head_pipeline_success?
logger.info("Pipeline Success")
return unless merge_request.mergeable?
logger.info("Merge request mergeable")
merge_request.merge_async(merge_request.merge_user_id, merge_request.merge_params)
end
@ -40,5 +45,9 @@ module AutoMerge
def notify(merge_request)
notification_service.async.merge_when_pipeline_succeeds(merge_request, current_user) if merge_request.saved_change_to_auto_merge_enabled?
end
def logger
@logger ||= Gitlab::AppLogger
end
end
end

View File

@ -22,8 +22,8 @@ module MergeRequests
result = yield
observe_result(mergeability_name, result)
observe("mergeability.#{mergeability_name}.duration_s", current_monotonic_time - op_started_at)
observe_sql_counters(mergeability_name, op_start_db_counters, current_db_counter_payload)
result
@ -31,7 +31,13 @@ module MergeRequests
private
attr_reader :destination, :merge_request
attr_reader :destination, :merge_request, :stored_result
def observe_result(name, result)
return unless result.respond_to?(:success?)
observe("mergeability.#{name}.successful", result.success?)
end
def observe(name, value)
observations[name.to_s].push(value)

View File

@ -0,0 +1,32 @@
- return if Gitlab.org_or_com?
- expanded = integration_expanded?('ai_access')
- token_is_present = @application_setting.ai_access_token.present?
- token_label = token_is_present ? s_('CodeSuggestionsSM|Enter new personal access token') : s_('CodeSuggestionsSM|Personal access token')
- token_value = token_is_present ? ApplicationSettingMaskedAttrs::MASK : ''
%section.settings.no-animate#js-ai-access-settings{ class: ('expanded' if expanded) }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= s_('CodeSuggestionsSM|Code Suggestions')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
%p
= s_('CodeSuggestionsSM|Enable Code Suggestion for users of this GitLab instance.')
= link_to sprite_icon('question-o'), code_suggestions_docs_url, target: '_blank', class: 'has-tooltip', title: _('More information')
.settings-content
= gitlab_ui_form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-ai-access-settings'), html: { class: 'fieldset-form', id: 'ai-access-settings' } do |f|
= form_errors(@application_setting)
%fieldset
.form-group
= f.gitlab_ui_checkbox_component :instance_level_code_suggestions_enabled,
s_('CodeSuggestionsSM|Turn on Code Suggestions for this instance. By turning on this feature, you:'),
help_text: code_suggestions_agreement
= f.label :ai_access_token, token_label, class: 'label-bold'
= f.password_field :ai_access_token, value: token_value, autocomplete: 'on', class: 'form-control gl-form-input', aria: { describedby: 'code_suggestions_token_explanation' }
%p.form-text.text-muted{ id: 'code_suggestions_token_explanation' }
= code_suggestions_token_explanation
= f.submit _('Save changes'), pajamas_button: true

View File

@ -109,3 +109,4 @@
= render 'admin/application_settings/floc'
= render_if_exists 'admin/application_settings/add_license'
= render 'admin/application_settings/jira_connect'
= render_if_exists 'admin/application_settings/ai_access'

View File

@ -10,6 +10,8 @@ en:
pwa_short_name: "PWA short name"
pwa_description: "PWA description"
pwa_icon: "Icon"
application_setting:
ai_access_token: "Personal access token"
incident_management/timeline_event:
note: 'Timeline text'
issue_link:

View File

@ -95,6 +95,8 @@ metadata:
description: Operations related to metadata of the GitLab instance
- name: metrics_user_starred_dashboards
description: Operations related to User-starred metrics dashboards
- name: ml_model_registry
description: Operations related to Model registry
- name: npm_packages
description: Operations related to NPM packages
- name: nuget_packages

View File

@ -0,0 +1,23 @@
# frozen_string_literal: true
class EnsureBackfillBigintIdIsCompleted < Gitlab::Database::Migration[2.1]
include Gitlab::Database::MigrationHelpers::ConvertToBigint
restrict_gitlab_migration gitlab_schema: :gitlab_ci
disable_ddl_transaction!
TABLE_NAME = :ci_pipeline_variables
def up
ensure_batched_background_migration_is_finished(
job_class_name: 'CopyColumnUsingBackgroundMigrationJob',
table_name: TABLE_NAME,
column_name: 'id',
job_arguments: [['id'], ['id_convert_to_bigint']]
)
end
def down
# no-op
end
end

View File

@ -0,0 +1,18 @@
# frozen_string_literal: true
class AddConcurrentIndexForCiPipelineVariablesBigintId < Gitlab::Database::Migration[2.1]
include Gitlab::Database::MigrationHelpers::ConvertToBigint
disable_ddl_transaction!
TABLE_NAME = :ci_pipeline_variables
INDEX_NAME = "index_#{TABLE_NAME}_on_id_convert_to_bigint"
def up
add_concurrent_index TABLE_NAME, :id_convert_to_bigint, unique: true, name: INDEX_NAME
end
def down
remove_concurrent_index_by_name TABLE_NAME, INDEX_NAME
end
end

View File

@ -0,0 +1 @@
4d84a87532b45436e64d0c919b361548b4b69b200ec3a91f454af718a51fd22a

View File

@ -0,0 +1 @@
7428675eac2c572aa3521df7af7e79f7cf1b6e8f8472e99c842dddf2f3c7ce77

View File

@ -30525,6 +30525,8 @@ CREATE INDEX index_ci_pipeline_schedules_on_owner_id_and_id_and_active ON ci_pip
CREATE INDEX index_ci_pipeline_schedules_on_project_id ON ci_pipeline_schedules USING btree (project_id);
CREATE UNIQUE INDEX index_ci_pipeline_variables_on_id_convert_to_bigint ON ci_pipeline_variables USING btree (id_convert_to_bigint);
CREATE UNIQUE INDEX index_ci_pipeline_variables_on_pipeline_id_and_key ON ci_pipeline_variables USING btree (pipeline_id, key);
CREATE INDEX index_ci_pipelines_config_on_pipeline_id ON ci_pipelines_config USING btree (pipeline_id);

View File

@ -29,13 +29,13 @@ To enable the Atlassian OmniAuth provider for passwordless authentication you mu
1. On your GitLab server, open the configuration file:
For Omnibus GitLab installations:
For Linux package installations:
```shell
sudo editor /etc/gitlab/gitlab.rb
```
For installations from source:
For self-compiled installations:
```shell
sudo -u git -H editor /home/git/gitlab/config/gitlab.yml
@ -47,7 +47,7 @@ To enable the Atlassian OmniAuth provider for passwordless authentication you mu
GitLab account.
1. Add the provider configuration for Atlassian:
For Omnibus GitLab installations:
For Linux package installations:
```ruby
gitlab_rails['omniauth_providers'] = [
@ -61,7 +61,7 @@ To enable the Atlassian OmniAuth provider for passwordless authentication you mu
]
```
For installations from source:
For self-compiled installations:
```yaml
- { name: "atlassian_oauth2",
@ -76,8 +76,8 @@ To enable the Atlassian OmniAuth provider for passwordless authentication you mu
1. Save the configuration file.
1. For the changes to take effect:
- If you installed via Omnibus, [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
- If you installed from source, [restart GitLab](../restart_gitlab.md#installations-from-source).
- If you installed using the Linux package, [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
- If you self-compiled your installation, [restart GitLab](../restart_gitlab.md#installations-from-source).
On the sign-in page there should now be an Atlassian icon below the regular sign in form. Select the icon to begin the authentication process.

View File

@ -37,16 +37,14 @@ To enable AWS Cognito as an authentication provider, complete the following step
1. Save changes for the app client settings.
1. Under **Domain name**, include the AWS domain name for your AWS Cognito application.
1. Under **App Clients**, find your app client ID. Select **Show details* to display the app client secret. These values correspond to the OAuth 2.0 Client ID and Client Secret. Save these values.
1. Under **App Clients**, find your app client ID. Select **Show details** to display the app client secret. These values correspond to the OAuth 2.0 Client ID and Client Secret. Save these values.
## Configure GitLab
1. Configure the [common settings](../../integration/omniauth.md#configure-common-settings)
to add `cognito` as a single sign-on provider. This enables Just-In-Time
account provisioning for users who do not have an existing GitLab account.
1. On your GitLab server, open the configuration file.
**For Omnibus installations**
1. On your GitLab server, open the configuration file. For Linux package installations:
```shell
sudo editor /etc/gitlab/gitlab.rb

View File

@ -26,19 +26,19 @@ this provider also allows Crowd authentication for Git-over-https requests.
1. On your GitLab server, open the configuration file.
**Omnibus:**
- Linux package installations:
```shell
sudo editor /etc/gitlab/gitlab.rb
```
```shell
sudo editor /etc/gitlab/gitlab.rb
```
**Source:**
- Self-compiled installations:
```shell
cd /home/git/gitlab
```shell
cd /home/git/gitlab
sudo -u git -H editor config/gitlab.yml
```
sudo -u git -H editor config/gitlab.yml
```
1. Configure the [common settings](../../integration/omniauth.md#configure-common-settings)
to add `crowd` as a single sign-on provider. This enables Just-In-Time
@ -46,39 +46,39 @@ this provider also allows Crowd authentication for Git-over-https requests.
1. Add the provider configuration:
**Omnibus:**
- Linux package installations:
```ruby
gitlab_rails['omniauth_providers'] = [
{
name: "crowd",
# label: "Provider name", # optional label for login button, defaults to "Crowd"
args: {
crowd_server_url: "CROWD_SERVER_URL",
application_name: "YOUR_APP_NAME",
application_password: "YOUR_APP_PASSWORD"
```ruby
gitlab_rails['omniauth_providers'] = [
{
name: "crowd",
# label: "Provider name", # optional label for login button, defaults to "Crowd"
args: {
crowd_server_url: "CROWD_SERVER_URL",
application_name: "YOUR_APP_NAME",
application_password: "YOUR_APP_PASSWORD"
}
}
}
]
```
]
```
**Source:**
- Self-compiled installations:
```yaml
- { name: 'crowd',
# label: 'Provider name', # optional label for login button, defaults to "Crowd"
args: {
crowd_server_url: 'CROWD_SERVER_URL',
application_name: 'YOUR_APP_NAME',
application_password: 'YOUR_APP_PASSWORD' } }
```
```yaml
- { name: 'crowd',
# label: 'Provider name', # optional label for login button, defaults to "Crowd"
args: {
crowd_server_url: 'CROWD_SERVER_URL',
application_name: 'YOUR_APP_NAME',
application_password: 'YOUR_APP_PASSWORD' } }
```
1. Change `CROWD_SERVER_URL` to the [base URL of your Crowd server](https://confluence.atlassian.com/crowdkb/how-to-change-the-crowd-base-url-245827278.html).
1. Change `YOUR_APP_NAME` to the application name from Crowd applications page.
1. Change `YOUR_APP_PASSWORD` to the application password you've set.
1. Save the configuration file.
1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) (Omnibus GitLab) or [restart](../restart_gitlab.md#installations-from-source) (source installations) for
the changes to take effect.
1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) (Linux package installations) or
[restart](../restart_gitlab.md#installations-from-source) (self-compiled installations) for the changes to take effect.
On the sign in page there should now be a Crowd tab in the sign in form.

View File

@ -12,13 +12,13 @@ JWT provides you with a secret key for you to use.
1. On your GitLab server, open the configuration file.
For Omnibus GitLab:
For Linux package installations:
```shell
sudo editor /etc/gitlab/gitlab.rb
```
For installations from source:
For self-compiled installations:
```shell
cd /home/git/gitlab
@ -30,7 +30,7 @@ JWT provides you with a secret key for you to use.
account provisioning for users who do not have an existing GitLab account.
1. Add the provider configuration.
For Omnibus GitLab:
For Linux package installations:
```ruby
gitlab_rails['omniauth_providers'] = [
@ -49,7 +49,7 @@ JWT provides you with a secret key for you to use.
]
```
For installation from source:
For self-compiled installations:
```yaml
- { name: 'jwt',
@ -75,9 +75,9 @@ JWT provides you with a secret key for you to use.
1. Change `YOUR_APP_SECRET` to the client secret and set `auth_url` to your redirect URL.
1. Save the configuration file.
1. For the changes to take effect:
- If you installed via Omnibus, [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
- If you installed from source, [restart GitLab](../restart_gitlab.md#installations-from-source).
1. For changes to take effect, if you:
- Used the Linux package to install GitLab, [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
- Self-compiled your GitLab installation, [restart GitLab](../restart_gitlab.md#installations-from-source).
On the sign in page there should now be a JWT icon below the regular sign in form.
Select the icon to begin the authentication process. JWT asks the user to

View File

@ -72,7 +72,7 @@ values obtained during the LDAP client configuration earlier:
- `cert`: The `.crt` file text from the downloaded certificate bundle
- `key`: The `.key` file text from the downloaded certificate bundle
**For Omnibus installations**
For Linux package installations:
1. Edit `/etc/gitlab/gitlab.rb`:
@ -142,9 +142,7 @@ values obtained during the LDAP client configuration earlier:
1. Save the file and [reconfigure](../../restart_gitlab.md#omnibus-gitlab-reconfigure) GitLab for the changes to take effect.
---
**For installations from source**
For self-compiled installations:
1. Edit `config/gitlab.yml`:

View File

@ -1037,8 +1037,8 @@ For more information on synchronizing users and groups between LDAP and GitLab,
## Move from LDAP to SAML
1. [Configure SAML](../../../integration/saml.md). Add `auto_link_ldap_user` to:
- [`gitlab.rb` for Omnibus](../../../integration/saml.html?tab=Linux+package+%28Omnibus%29).
- [`values.yml` for Kubernetes](../../../integration/saml.html?tab=Helm+chart+%28Kubernetes%29).
- [`gitlab.rb` for Linux package installations](../../../integration/saml.html?tab=Linux+package+%28Omnibus%29).
- [`values.yml` for Helm chart installations](../../../integration/saml.html?tab=Helm+chart+%28Kubernetes%29).
For more information, see the [initial settings for all providers](../../../integration/omniauth.md#configure-initial-settings).
1. Optional. [Disable the LDAP auth from the sign-in page](#disable-ldap-web-sign-in).

View File

@ -16,7 +16,7 @@ The OpenID Connect provides you with a client's details and secret for you to us
1. On your GitLab server, open the configuration file.
For Omnibus GitLab:
For Linux package installations:
```shell
sudo editor /etc/gitlab/gitlab.rb
@ -35,7 +35,7 @@ The OpenID Connect provides you with a client's details and secret for you to us
1. Add the provider configuration.
For Omnibus GitLab:
For Linux package installations:
```ruby
gitlab_rails['omniauth_providers'] = [
@ -63,7 +63,7 @@ The OpenID Connect provides you with a client's details and secret for you to us
]
```
For Omnibus GitLab with multiple identity providers:
For Linux package installations with multiple identity providers:
```ruby
{ 'name' => 'openid_connect',
@ -108,7 +108,7 @@ The OpenID Connect provides you with a client's details and secret for you to us
NOTE:
For more information on using multiple identity providers with OIDC, see [issue 5992](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5992).
For installation from source:
For self-compiled installations:
```yaml
- { name: 'openid_connect', # do not change this parameter
@ -184,10 +184,10 @@ The OpenID Connect provides you with a client's details and secret for you to us
- `jwks_uri` is the URL to the endpoint where the Token signer publishes its keys.
1. Save the configuration file.
1. For changes to take effect, if you installed GitLab:
1. For changes to take effect, if you:
- With Omnibus, [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
- From source, [restart GitLab](../restart_gitlab.md#installations-from-source).
- Used the Linux package to install GitLab, [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
- Self-compiled your GitLab installation, [restart GitLab](../restart_gitlab.md#installations-from-source).
On the sign in page, you have an OpenID Connect option below the regular sign in form.
Select this option to begin the authentication process. The OpenID Connect provider
@ -197,7 +197,7 @@ by the client. You are redirected to GitLab and signed in.
## Example configurations
The following configurations illustrate how to set up OpenID with
different providers with Omnibus GitLab.
different providers when using the GitLab Linux package installation.
### Configure Google
@ -240,7 +240,7 @@ you need the following information:
[Microsoft Quickstart Register an Application](https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) documentation
to obtain the tenant ID, client ID, and client secret for your app.
Example Omnibus configuration block:
Example configuration block for Linux package installations:
```ruby
gitlab_rails['omniauth_providers'] = [
@ -372,7 +372,7 @@ but `LocalAccounts` authenticates against local Active Directory accounts. Befor
```
1. Configure the issuer URL with the custom policy used for `signup_signin`. For example, this is
the Omnibus configuration with a custom policy for `b2c_1a_signup_signin`:
the configuration with a custom policy for `b2c_1a_signup_signin` for Linux package installations:
```ruby
gitlab_rails['omniauth_providers'] = [
@ -432,7 +432,7 @@ HS256 or HS358) to sign tokens. Public key encryption algorithms are:
1. Select **Realm Settings > Tokens > Default Signature Algorithm**.
1. Configure the signature algorithm.
Example Omnibus configuration block:
Example configuration block for Linux package installations:
```ruby
gitlab_rails['omniauth_providers'] = [
@ -556,7 +556,7 @@ For your app, complete the following steps on Casdoor:
See the [Casdoor documentation](https://casdoor.org/docs/integration/ruby/gitlab) for more details.
Example Omnibus GitLab configuration (file path: `/etc/gitlab/gitlab.rb`):
Example configuration for Linux package installations (file path: `/etc/gitlab/gitlab.rb`):
```ruby
gitlab_rails['omniauth_providers'] = [
@ -617,7 +617,7 @@ This is not compatible with [configuring users based on OIDC group membership](#
The following example configurations show how to offer different levels of authentication, one option with 2FA and one without 2FA.
For Omnibus GitLab:
For Linux package installations:
```ruby
gitlab_rails['omniauth_providers'] = [
@ -668,7 +668,7 @@ gitlab_rails['omniauth_providers'] = [
]
```
For installation from source:
For self-compiled installations:
```yaml
- { name: 'openid_connect',
@ -774,7 +774,7 @@ response to require users to be members of a certain group, configure GitLab to
If you do not set `required_groups` or leave the setting empty, any user authenticated by the IdP through OIDC can use GitLab.
For Omnibus GitLab:
For Linux package installations:
1. Edit `/etc/gitlab/gitlab.rb`:
@ -808,7 +808,7 @@ For Omnibus GitLab:
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure)
for the changes to take effect.
For installation from source:
For self-compiled installations:
1. Edit `/home/git/gitlab/config/gitlab.yml`:
@ -853,7 +853,7 @@ based on group membership, configure GitLab to identify:
[external user](../../user/admin_area/external_users.md), using the
`external_groups` setting.
For Omnibus GitLab:
For Linux package installations:
1. Edit `/etc/gitlab/gitlab.rb`:
@ -887,7 +887,7 @@ For Omnibus GitLab:
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure)
for the changes to take effect.
For installation from source:
For self-compiled installations:
1. Edit `/home/git/gitlab/config/gitlab.yml`:
@ -930,7 +930,7 @@ response to assign users as administrator based on group membership, configure G
- Which group memberships grant the user administrator access, using the
`admin_groups` setting.
For Omnibus GitLab:
For Linux package installations:
1. Edit `/etc/gitlab/gitlab.rb`:
@ -964,7 +964,7 @@ For Omnibus GitLab:
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure)
for the changes to take effect.
For installation from source:
For self-compiled installations:
1. Edit `/home/git/gitlab/config/gitlab.yml`:

View File

@ -115,7 +115,7 @@ more information, see [the relevant issue](https://gitlab.com/gitlab-org/gitlab/
## Configure GitLab for smartcard authentication
**For Omnibus installations**
For Linux package installations:
1. Edit `/etc/gitlab/gitlab.rb`:
@ -140,9 +140,7 @@ more information, see [the relevant issue](https://gitlab.com/gitlab-org/gitlab/
1. Save the file and [reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure)
GitLab for the changes to take effect.
---
**For installations from source**
For self-compiled installations:
1. Configure NGINX to request a client side certificate
@ -237,7 +235,7 @@ more information, see [the relevant issue](https://gitlab.com/gitlab-org/gitlab/
### Additional steps when using SAN extensions
**For Omnibus installations**
For Linux package installations:
1. Add to `/etc/gitlab/gitlab.rb`:
@ -248,7 +246,7 @@ more information, see [the relevant issue](https://gitlab.com/gitlab-org/gitlab/
1. Save the file and [reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure)
GitLab for the changes to take effect.
**For installations from source**
For self-compiled installations:
1. Add the `san_extensions` line to `config/gitlab.yml` within the smartcard section:
@ -267,7 +265,7 @@ more information, see [the relevant issue](https://gitlab.com/gitlab-org/gitlab/
### Additional steps when authenticating against an LDAP server
**For Omnibus installations**
For Linux package installations:
1. Edit `/etc/gitlab/gitlab.rb`:
@ -284,7 +282,7 @@ more information, see [the relevant issue](https://gitlab.com/gitlab-org/gitlab/
1. Save the file and [reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure)
GitLab for the changes to take effect.
**For installations from source**
For self-compiled installations:
1. Edit `config/gitlab.yml`:
@ -304,7 +302,7 @@ more information, see [the relevant issue](https://gitlab.com/gitlab-org/gitlab/
### Require browser session with smartcard sign-in for Git access
**For Omnibus installations**
For Linux package installations:
1. Edit `/etc/gitlab/gitlab.rb`:
@ -315,7 +313,7 @@ more information, see [the relevant issue](https://gitlab.com/gitlab-org/gitlab/
1. Save the file and [reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure)
GitLab for the changes to take effect.
**For installations from source**
For self-compiled installations:
1. Edit `config/gitlab.yml`:

View File

@ -21,12 +21,12 @@ If you use self-managed GitLab, you must install an agent server or specify an e
As a GitLab administrator, you can install the agent server:
- For [Omnibus installations](#for-omnibus).
- For [GitLab Helm Chart installations](#for-gitlab-helm-chart).
- For [Linux package installations](#for-linux-package-installations).
- For [GitLab Helm chart installations](#for-gitlab-helm-chart).
### For Omnibus
### For Linux package installations
You can enable the agent server for [Omnibus](https://docs.gitlab.com/omnibus/) package installations on a single node, or on multiple nodes at once.
You can enable the agent server for Linux package installations on a single node, or on multiple nodes at once.
#### Enable on a single node
@ -167,7 +167,7 @@ service logs by running the following command:
kubectl logs -f -l=app=kas -n <YOUR-GITLAB-NAMESPACE>
```
In Omnibus GitLab, find the logs in `/var/log/gitlab/gitlab-kas/`.
In Linux package installations, find the logs in `/var/log/gitlab/gitlab-kas/`.
You can also [troubleshoot issues with individual agents](../../user/clusters/agent/troubleshooting.md).
@ -212,7 +212,7 @@ When the agent server tries to connect to the GitLab API, the following error mi
{"level":"error","time":"2021-08-16T14:56:47.289Z","msg":"GetAgentInfo()","correlation_id":"01FD7QE35RXXXX8R47WZFBAXTN","grpc_service":"gitlab.agent.reverse_tunnel.rpc.ReverseTunnel","grpc_method":"Connect","error":"Get \"https://gitlab.example.com/api/v4/internal/kubernetes/agent_info\": dial tcp 172.17.0.4:443: connect: connection refused"}
```
To fix this issue for [Omnibus](https://docs.gitlab.com/omnibus/) package installations,
To fix this issue for Linux package installations,
set the following parameter in `/etc/gitlab/gitlab.rb`. Replace `gitlab.example.com` with your GitLab instance's hostname:
```ruby

View File

@ -211,6 +211,71 @@ make Prometheus scrape them over HTTPS, and support for it is being discussed
Hence, it is not technically possible to turn off this HTTP listener without
losing Prometheus metrics.
### Using an encrypted SSL key
> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/7799) in GitLab 16.1.
Puma supports the use of an encrypted private SSL key, which can be
decrypted at runtime. The following instructions illustrate how to
configure this:
1. Encrypt the key with a password if it is not already:
```shell
openssl rsa -aes256 -in /path/to/ssl-key.pem -out /path/to/encrypted-ssl-key.pem
```
Enter in a password twice to write the encrypted file. In this
example, we use `some-password-here`.
1. Create a script or executable that prints the password. For
example, create a basic script in
`/var/opt/gitlab/gitlab-rails/etc/puma-ssl-key-password` that echoes
the password:
```shell
#!/bin/sh
echo some-password-here
```
Note that in production, you should avoid storing the password on
disk and use a secure mechanism for retrieving a password, such as
Vault. For example, the script might look like:
```shell
#!/bin/sh
export VAULT_ADDR=http://vault-password-distribution-point:8200
export VAULT_TOKEN=<some token>
echo "$(vault kv get -mount=secret puma-ssl-password)"
```
1. Ensure the Puma process has sufficient permissions to execute the
script and to read the encrypted key:
```shell
chown git:git /var/opt/gitlab/gitlab-rails/etc/puma-ssl-key-password
chmod 770 /var/opt/gitlab/gitlab-rails/etc/puma-ssl-key-password
chmod 660 /path/to/encrypted-ssl-key.pem
```
1. Edit `/etc/gitlab/gitlab.rb`, and replace `puma['ssl_certificate_key']` with the encrypted key and specify
`puma['ssl_key_password_command]`:
```ruby
puma['ssl_certificate_key'] = '/path/to/encrypted-ssl-key.pem'
puma['ssl_key_password_command'] = '/var/opt/gitlab/gitlab-rails/etc/puma-ssl-key-password'
```
1. Reconfigure GitLab:
```shell
sudo gitlab-ctl reconfigure
```
1. If GitLab comes up successfully, you should be able to remove the
unencrypted SSL key that was stored on the GitLab instance.
## Switch from Unicorn to Puma
NOTE:

View File

@ -30,6 +30,7 @@ Read more about update policies and warnings in the PostgreSQL
| GitLab version | PostgreSQL versions | Default version for fresh installs | Default version for upgrades | Notes |
| -------------- | --------------------- | ---------------------------------- | ---------------------------- | ----- |
| 16.0 | 13.11 | 13.11 | 13.11 | |
| 15.6 | 12.12, 13.8 | 13.8 | 12.12 | For upgrades, users can manually upgrade to 13.8 following the [upgrade documentation](https://docs.gitlab.com/omnibus/settings/database.html#gitlab-150-and-later). |
| 15.0 | 12.10, 13.6 | 13.6 | 12.10 | For upgrades, users can manually upgrade to 13.6 following the [upgrade documentation](https://docs.gitlab.com/omnibus/settings/database.html#gitlab-150-and-later). |
| 14.1 | 12.7, 13.3 | 12.7 | 12.7 | PostgreSQL 13 available for fresh installations if not using [Geo](../geo/index.md#requirements-for-running-geo) or [Patroni](../postgresql/index.md#postgresql-replication-and-failover-with-omnibus-gitlab).

View File

@ -32,6 +32,8 @@ As a user, to delete your own account:
NOTE:
On GitLab.com, there is a seven day delay between a user deleting their own account and deletion of the user record. During this time, that user is [blocked](../../admin_area/moderate_users.md#block-a-user) and a new account with the same email address or username cannot be created.
Unblocking the account does not undo the deletion because the account will still be in the deletion queue, and there is no quick method to reverse this process.
## Delete users and user contributions **(FREE SELF)**
As an administrator, to delete a user account:

View File

@ -255,6 +255,7 @@ module API
mount ::API::Metadata
mount ::API::Metrics::Dashboard::Annotations
mount ::API::Metrics::UserStarredDashboards
mount ::API::MlModelPackages
mount ::API::Namespaces
mount ::API::NpmGroupPackages
mount ::API::NpmInstancePackages

View File

@ -0,0 +1,111 @@
# frozen_string_literal: true
module API
class MlModelPackages < ::API::Base
include APIGuard
include ::API::Helpers::Authentication
ML_MODEL_PACKAGES_REQUIREMENTS = {
package_name: API::NO_SLASH_URL_PART_REGEX,
file_name: API::NO_SLASH_URL_PART_REGEX
}.freeze
ALLOWED_STATUSES = %w[default hidden].freeze
feature_category :mlops
urgency :low
after_validation do
require_packages_enabled!
authenticate_non_get!
not_found! unless can?(current_user, :read_model_registry, user_project)
end
authenticate_with do |accept|
accept.token_types(:personal_access_token, :deploy_token, :job_token)
.sent_through(:http_token)
end
helpers do
include ::API::Helpers::PackagesHelpers
include ::API::Helpers::Packages::BasicAuthHelpers
def project
authorized_user_project
end
def max_file_size_exceeded?
project.actual_limits.exceeded?(:ml_model_max_file_size, params[:file].size)
end
end
params do
requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project'
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
namespace ':id/packages/ml_models' do
params do
requires :package_name, type: String, desc: 'Package name', regexp: Gitlab::Regex.ml_model_name_regex,
file_path: true
requires :package_version, type: String, desc: 'Package version',
regexp: Gitlab::Regex.ml_model_version_regex
requires :file_name, type: String, desc: 'Package file name',
regexp: Gitlab::Regex.ml_model_file_name_regex, file_path: true
optional :status, type: String, values: ALLOWED_STATUSES, desc: 'Package status'
end
namespace ':package_name/*package_version/:file_name', requirements: ML_MODEL_PACKAGES_REQUIREMENTS do
desc 'Workhorse authorize model package file' do
detail 'Introduced in GitLab 16.1'
success code: 200
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[ml_model_registry]
end
put 'authorize' do
authorize_workhorse!(subject: project, maximum_size: project.actual_limits.ml_model_max_file_size)
end
desc 'Workhorse upload model package file' do
detail 'Introduced in GitLab 16.1'
success code: 201
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[ml_model_registry]
end
params do
requires :file,
type: ::API::Validations::Types::WorkhorseFile,
desc: 'The package file to be published (generated by Multipart middleware)',
documentation: { type: 'file' }
end
put do
authorize_upload!(project)
bad_request!('File is too large') if max_file_size_exceeded?
create_package_file_params = declared(params).merge(build: current_authenticated_job)
package_file = ::Packages::MlModel::CreatePackageFileService
.new(project, current_user, create_package_file_params)
.execute
bad_request!('Package creation failed') unless package_file
created!
rescue ObjectStorage::RemoteStoreError => e
Gitlab::ErrorTracking.track_exception(e, extra: { file_name: params[:file_name], project_id: project.id })
forbidden!
end
end
end
end
end
end

View File

@ -623,6 +623,18 @@ module Gitlab
def x509_subject_key_identifier_regex
@x509_subject_key_identifier_regex ||= /\A(?:\h{2}:)*\h{2}\z/.freeze
end
def ml_model_version_regex
maven_version_regex
end
def ml_model_name_regex
package_name_regex
end
def ml_model_file_name_regex
maven_file_name_regex
end
end
end

View File

@ -11070,6 +11070,27 @@ msgstr ""
msgid "CodeSuggestionsAlert|Get started with Code Suggestions, available for free during the beta period."
msgstr ""
msgid "CodeSuggestionsSM|&#8226; Agree to the %{terms_link_start}GitLab Testing Agreement%{link_end}.%{br} &#8226; Acknowledge that GitLab will send data from the instance, including personal data, to Google for cloud hosting.%{br} &nbsp;&nbsp;&nbsp;We may also send data to %{ai_docs_link_start}third-party AI providers%{link_end} to provide this feature."
msgstr ""
msgid "CodeSuggestionsSM|Code Suggestions"
msgstr ""
msgid "CodeSuggestionsSM|Enable Code Suggestion for users of this GitLab instance."
msgstr ""
msgid "CodeSuggestionsSM|Enter new personal access token"
msgstr ""
msgid "CodeSuggestionsSM|Personal access token"
msgstr ""
msgid "CodeSuggestionsSM|Turn on Code Suggestions for this instance. By turning on this feature, you:"
msgstr ""
msgid "CodeSuggestionsSM|Your personal access token from GitLab.com. See the %{link_start}documentation%{link_end} for information on creating a personal access token."
msgstr ""
msgid "CodeSuggestions|%{link_start}What are code suggestions?%{link_end}"
msgstr ""
@ -54137,6 +54158,9 @@ msgstr ""
msgid "is read-only"
msgstr ""
msgid "is required to enable Code Suggestions"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""

View File

@ -133,8 +133,8 @@ function disable_sign_ups() {
# We use this weird syntax because we need to pass a one-liner ruby command to a Kubernetes container via kubectl.
read -r -d '' multiline_ruby_code <<RUBY
user = User.find_by_username('root');
puts 'Error: Could not find root user. Check that the database was properly seeded'; exit(1) unless user;
token = user.personal_access_tokens.create(scopes: [:api], name: 'Token to disable sign-ups');
(puts 'Error: Could not find root user. Check that the database was properly seeded'; exit(1)) unless user;
token = user.personal_access_tokens.create(scopes: [:api], name: 'Token to disable sign-ups', expires_at: 30.days.from_now);
token.set_token('${REVIEW_APPS_ROOT_TOKEN}');
begin;
token.save!;

View File

@ -31,4 +31,18 @@ RSpec.describe Admin::ApplicationSettings::SettingsHelper do
})
end
end
describe 'Code Suggestions for Self-Managed instances', feature_category: :code_suggestions do
describe '#code_suggestions_token_explanation' do
subject { helper.code_suggestions_token_explanation }
it { is_expected.to include 'https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token' }
end
describe '#code_suggestions_agreement' do
subject { helper.code_suggestions_agreement }
it { is_expected.to include 'https://about.gitlab.com/handbook/legal/testing-agreement/' }
end
end
end

View File

@ -11,7 +11,7 @@ RSpec.describe Sidebars::Admin::Menus::AbuseReportsMenu, feature_category: :navi
it_behaves_like 'Admin menu without sub menus', active_routes: { controller: :abuse_reports }
describe '#pill_count' do
let_it_be(:user) { create(:user, :admin) }
let(:user) { build_stubbed(:user, :admin) }
let(:context) { Sidebars::Context.new(current_user: user, container: nil) }

View File

@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Sidebars::Admin::Menus::MonitoringMenu, feature_category: :navigation do
let_it_be(:user) { create(:user, :admin) }
let(:user) { build_stubbed(:user, :admin) }
let(:context) { Sidebars::Context.new(current_user: user, container: nil) }
let(:menu) { described_class.new(context) }

View File

@ -2,7 +2,7 @@
require 'fast_spec_helper'
RSpec.describe Sidebars::Concerns::ContainerWithHtmlOptions do
RSpec.describe Sidebars::Concerns::ContainerWithHtmlOptions, feature_category: :navigation do
subject do
Class.new do
include Sidebars::Concerns::ContainerWithHtmlOptions

View File

@ -2,7 +2,7 @@
require 'fast_spec_helper'
RSpec.describe Sidebars::Concerns::LinkWithHtmlOptions do
RSpec.describe Sidebars::Concerns::LinkWithHtmlOptions, feature_category: :navigation do
let(:options) { {} }
subject { Class.new { include Sidebars::Concerns::LinkWithHtmlOptions }.new }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Sidebars::Groups::Menus::CiCdMenu do
RSpec.describe Sidebars::Groups::Menus::CiCdMenu, feature_category: :navigation do
let_it_be(:owner) { create(:user) }
let_it_be(:root_group) do
build(:group, :private).tap do |g|

View File

@ -2,9 +2,9 @@
require 'spec_helper'
RSpec.describe Sidebars::Groups::Menus::ObservabilityMenu do
let_it_be(:owner) { create(:user) }
let_it_be(:root_group) do
RSpec.describe Sidebars::Groups::Menus::ObservabilityMenu, feature_category: :navigation do
let(:owner) { build_stubbed(:user) }
let(:root_group) do
build(:group, :private).tap do |g|
g.add_owner(owner)
end

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Sidebars::Groups::Menus::SettingsMenu, :with_license do
RSpec.describe Sidebars::Groups::Menus::SettingsMenu, :with_license, feature_category: :navigation do
let_it_be(:owner) { create(:user) }
let_it_be_with_refind(:group) do

View File

@ -2,7 +2,7 @@
require 'fast_spec_helper'
RSpec.describe Sidebars::MenuItem do
RSpec.describe Sidebars::MenuItem, feature_category: :navigation do
let(:title) { 'foo' }
let(:html_options) { {} }
let(:menu_item) { described_class.new(title: title, active_routes: {}, link: '', container_html_options: html_options) }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Sidebars::Projects::Context do
RSpec.describe Sidebars::Projects::Context, feature_category: :navigation do
let(:project) { build(:project) }
subject { described_class.new(current_user: nil, container: project) }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::AnalyticsMenu do
RSpec.describe Sidebars::Projects::Menus::AnalyticsMenu, feature_category: :navigation do
let_it_be_with_refind(:project) { create(:project, :repository) }
let_it_be(:guest) do
create(:user).tap { |u| project.add_guest(u) }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::CiCdMenu do
RSpec.describe Sidebars::Projects::Menus::CiCdMenu, feature_category: :navigation do
let(:project) { build(:project) }
let(:user) { project.first_owner }
let(:can_view_pipeline_editor) { true }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::ConfluenceMenu do
RSpec.describe Sidebars::Projects::Menus::ConfluenceMenu, feature_category: :navigation do
let_it_be_with_refind(:project) { create(:project, has_external_wiki: true) }
let(:user) { project.first_owner }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::ExternalIssueTrackerMenu do
RSpec.describe Sidebars::Projects::Menus::ExternalIssueTrackerMenu, feature_category: :navigation do
let(:project) { build(:project) }
let(:user) { project.first_owner }
let(:jira_issues_integration_active) { false }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::HiddenMenu do
RSpec.describe Sidebars::Projects::Menus::HiddenMenu, feature_category: :navigation do
let_it_be(:project) { create(:project, :repository) }
let(:user) { project.first_owner }

View File

@ -71,7 +71,7 @@ RSpec.describe Sidebars::Projects::Menus::IssuesMenu, feature_category: :navigat
context 'when there are open issues' do
it 'returns the number of open issues' do
create_list(:issue, 2, :opened, project: project)
create(:issue, :closed, project: project)
build_stubbed(:issue, :closed, project: project)
expect(subject.pill_count).to eq '2'
end

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::MonitorMenu do
RSpec.describe Sidebars::Projects::Menus::MonitorMenu, feature_category: :navigation do
let_it_be_with_refind(:project) { create(:project) }
let(:user) { project.first_owner }

View File

@ -2,8 +2,8 @@
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::SettingsMenu do
let_it_be(:project) { create(:project) }
RSpec.describe Sidebars::Projects::Menus::SettingsMenu, feature_category: :navigation do
let(:project) { build_stubbed(:project) }
let(:user) { project.first_owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }

View File

@ -2,6 +2,6 @@
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::ZentaoMenu do
RSpec.describe Sidebars::Projects::Menus::ZentaoMenu, feature_category: :navigation do
it_behaves_like 'ZenTao menu with CE version'
end

View File

@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Sidebars::Projects::SuperSidebarPanel, feature_category: :navigation do
let_it_be(:project) { create(:project, :repository) }
let(:project) { build_stubbed(:project, :repository) }
let(:user) { project.first_owner }
let(:context) do

View File

@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe Sidebars::Search::Panel, feature_category: :navigation do
let_it_be(:current_user) { create(:user) }
let_it_be(:user) { create(:user) }
let(:current_user) { build_stubbed(:user) }
let(:user) { build_stubbed(:user) }
let(:context) { Sidebars::Context.new(current_user: current_user, container: user) }
let(:panel) { described_class.new(context) }

View File

@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe Sidebars::UserProfile::Panel, feature_category: :navigation do
let_it_be(:current_user) { create(:user) }
let_it_be(:user) { create(:user) }
let(:current_user) { build_stubbed(:user) }
let(:user) { build_stubbed(:user) }
let(:context) { Sidebars::Context.new(current_user: current_user, container: user) }

View File

@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Sidebars::UserSettings::Panel, feature_category: :navigation do
let_it_be(:user) { create(:user) }
let(:user) { build_stubbed(:user) }
let(:context) { Sidebars::Context.new(current_user: user, container: nil) }

View File

@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Sidebars::YourWork::Menus::IssuesMenu, feature_category: :navigation do
let(:user) { create(:user) }
let(:user) { build_stubbed(:user) }
let(:context) { Sidebars::Context.new(current_user: user, container: nil) }
subject { described_class.new(context) }

View File

@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Sidebars::YourWork::Menus::MergeRequestsMenu, feature_category: :navigation do
let_it_be(:user) { create(:user) }
let(:user) { build_stubbed(:user) }
let(:context) { Sidebars::Context.new(current_user: user, container: nil) }

View File

@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Sidebars::YourWork::Menus::TodosMenu, feature_category: :navigation do
let(:user) { create(:user) }
let(:user) { build_stubbed(:user) }
let(:context) { Sidebars::Context.new(current_user: user, container: nil) }
subject { described_class.new(context) }

View File

@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Sidebars::YourWork::Panel, feature_category: :navigation do
let_it_be(:user) { create(:user) }
let(:user) { build_stubbed(:user) }
let(:context) { Sidebars::Context.new(current_user: user, container: nil) }

View File

@ -1650,4 +1650,29 @@ RSpec.describe ApplicationSetting, feature_category: :shared, type: :model do
expect(setting.personal_access_tokens_disabled?).to eq(false)
end
end
describe '#ai_access_token' do
context 'when `instance_level_code_suggestions_enabled` is true' do
before do
setting.instance_level_code_suggestions_enabled = true
end
it { is_expected.not_to allow_value(nil).for(:ai_access_token) }
end
context 'when `instance_level_code_suggestions_enabled` is false' do
before do
setting.instance_level_code_suggestions_enabled = false
end
it { is_expected.to allow_value(nil).for(:ai_access_token) }
end
it 'does not modify the token if it is unchanged in the form' do
setting.ai_access_token = 'foo'
setting.ai_access_token = ApplicationSettingMaskedAttrs::MASK
expect(setting.ai_access_token).to eq('foo')
end
end
end

View File

@ -0,0 +1,200 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ::API::MlModelPackages, feature_category: :mlops do
include HttpBasicAuthHelpers
include PackagesManagerApiSpecHelpers
include WorkhorseHelpers
using RSpec::Parameterized::TableSyntax
include_context 'workhorse headers'
let_it_be(:project, reload: true) { create(:project) }
let_it_be(:personal_access_token) { create(:personal_access_token) }
let_it_be(:job) { create(:ci_build, :running, user: personal_access_token.user, project: project) }
let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
let_it_be(:another_project, reload: true) { create(:project) }
let_it_be(:tokens) do
{
personal_access_token: personal_access_token.token,
deploy_token: deploy_token.token,
job_token: job.token
}
end
let(:user) { personal_access_token.user }
let(:user_role) { :developer }
let(:member) { true }
let(:ci_build) { create(:ci_build, :running, user: user, project: project) }
let(:project_to_enable_ff) { project }
let(:headers) { {} }
shared_context 'ml model authorize permissions table' do # rubocop:disable RSpec/ContextWording
# rubocop:disable Metrics/AbcSize
# :visibility, :user_role, :member, :token_type, :valid_token, :expected_status
def authorize_permissions_table
:public | :developer | true | :personal_access_token | true | :success
:public | :guest | true | :personal_access_token | true | :forbidden
:public | :developer | true | :personal_access_token | false | :unauthorized
:public | :guest | true | :personal_access_token | false | :unauthorized
:public | :developer | false | :personal_access_token | true | :forbidden
:public | :guest | false | :personal_access_token | true | :forbidden
:public | :developer | false | :personal_access_token | false | :unauthorized
:public | :guest | false | :personal_access_token | false | :unauthorized
:public | :anonymous | false | :personal_access_token | true | :unauthorized
:private | :developer | true | :personal_access_token | true | :success
:private | :guest | true | :personal_access_token | true | :forbidden
:private | :developer | true | :personal_access_token | false | :unauthorized
:private | :guest | true | :personal_access_token | false | :unauthorized
:private | :developer | false | :personal_access_token | true | :not_found
:private | :guest | false | :personal_access_token | true | :not_found
:private | :developer | false | :personal_access_token | false | :unauthorized
:private | :guest | false | :personal_access_token | false | :unauthorized
:private | :anonymous | false | :personal_access_token | true | :unauthorized
:public | :developer | true | :job_token | true | :success
:public | :guest | true | :job_token | true | :forbidden
:public | :developer | true | :job_token | false | :unauthorized
:public | :guest | true | :job_token | false | :unauthorized
:public | :developer | false | :job_token | true | :forbidden
:public | :guest | false | :job_token | true | :forbidden
:public | :developer | false | :job_token | false | :unauthorized
:public | :guest | false | :job_token | false | :unauthorized
:private | :developer | true | :job_token | true | :success
:private | :guest | true | :job_token | true | :forbidden
:private | :developer | true | :job_token | false | :unauthorized
:private | :guest | true | :job_token | false | :unauthorized
:private | :developer | false | :job_token | true | :not_found
:private | :guest | false | :job_token | true | :not_found
:private | :developer | false | :job_token | false | :unauthorized
:private | :guest | false | :job_token | false | :unauthorized
:public | :developer | true | :deploy_token | true | :success
:public | :developer | true | :deploy_token | false | :unauthorized
:private | :developer | true | :deploy_token | true | :success
:private | :developer | true | :deploy_token | false | :unauthorized
end
# rubocop:enable Metrics/AbcSize
end
before do
project.send("add_#{user_role}", user) if member && user_role != :anonymous
end
subject(:api_response) do
request
response
end
describe 'PUT /api/v4/projects/:id/packages/ml_models/:package_name/:package_version/:file_name/authorize' do
include_context 'ml model authorize permissions table'
let(:token) { tokens[:personal_access_token] }
let(:user_headers) { { 'HTTP_AUTHORIZATION' => token } }
let(:headers) { user_headers.merge(workhorse_headers) }
let(:request) { authorize_upload_file(headers) }
describe 'user access' do
where(:visibility, :user_role, :member, :token_type, :valid_token, :expected_status) do
authorize_permissions_table
end
with_them do
let(:token) { valid_token ? tokens[token_type] : 'invalid-token123' }
let(:user_headers) { user_role == :anonymous ? {} : { 'HTTP_AUTHORIZATION' => token } }
before do
project.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value(visibility.to_s))
end
it { is_expected.to have_gitlab_http_status(expected_status) }
end
it_behaves_like 'Endpoint not found if read_model_registry not available'
end
describe 'application security' do
where(:param_name, :param_value) do
:package_name | 'my-package/../'
:package_name | 'my-package%2f%2e%2e%2f'
:file_name | '../.ssh%2fauthorized_keys'
:file_name | '%2e%2e%2f.ssh%2fauthorized_keys'
end
with_them do
let(:request) { authorize_upload_file(headers, param_name => param_value) }
it 'rejects malicious request' do
is_expected.to have_gitlab_http_status(:bad_request)
end
end
end
end
describe 'PUT /api/v4/projects/:id/packages/ml_models/:package_name/:package_version/:file_name' do
include_context 'ml model authorize permissions table'
let_it_be(:file_name) { 'model.md5' }
let(:token) { tokens[:personal_access_token] }
let(:user_headers) { { 'HTTP_AUTHORIZATION' => token } }
let(:headers) { user_headers.merge(workhorse_headers) }
let(:params) { { file: temp_file(file_name) } }
let(:file_key) { :file }
let(:send_rewritten_field) { true }
let(:request) do
upload_file(headers)
end
describe 'success' do
it 'creates a new package' do
expect { api_response }.to change { Packages::PackageFile.count }.by(1)
expect(api_response).to have_gitlab_http_status(:created)
end
end
describe 'user access' do
where(:visibility, :user_role, :member, :token_type, :valid_token, :expected_status) do
authorize_permissions_table
end
with_them do
let(:token) { valid_token ? tokens[token_type] : 'invalid-token123' }
let(:user_headers) { user_role == :anonymous ? {} : { 'HTTP_AUTHORIZATION' => token } }
before do
project.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value(visibility.to_s))
end
if params[:expected_status] == :success
it_behaves_like 'process ml model package upload'
else
it { is_expected.to have_gitlab_http_status(expected_status) }
end
end
it_behaves_like 'Endpoint not found if read_model_registry not available'
end
end
def authorize_upload_file(request_headers, package_name: 'mypackage', file_name: 'myfile.tar.gz')
url = "/projects/#{project.id}/packages/ml_models/#{package_name}/0.0.1/#{file_name}/authorize"
put api(url), headers: request_headers
end
def upload_file(request_headers, package_name: 'mypackage')
url = "/projects/#{project.id}/packages/ml_models/#{package_name}/0.0.1/#{file_name}"
workhorse_finalize(
api(url),
method: :put,
file_key: file_key,
params: params,
headers: request_headers,
send_rewritten_field: send_rewritten_field
)
end
end

View File

@ -40,6 +40,37 @@ RSpec.describe MergeRequests::Mergeability::Logger, :request_store, feature_cate
logger.commit
end
context 'when block value responds to #success?' do
let(:success?) { true }
let(:check_result) { instance_double(Gitlab::MergeRequests::Mergeability::CheckResult, success?: success?) }
let(:extra_data) do
{
'mergeability.expensive_operation.successful.values' => [success?]
}
end
shared_examples_for 'success state logger' do
it 'records operation success state' do
expect_next_instance_of(Gitlab::AppJsonLogger) do |app_logger|
expect(app_logger).to receive(:info).with(match(a_hash_including(loggable_data(**extra_data))))
end
expect(logger.instrument(mergeability_name: :expensive_operation) { check_result }).to eq(check_result)
logger.commit
end
end
it_behaves_like 'success state logger'
context 'when not successful' do
let(:success?) { false }
it_behaves_like 'success state logger'
end
end
context 'with multiple observations' do
let(:operation_count) { 2 }

View File

@ -0,0 +1,108 @@
# frozen_string_literal: true
RSpec.shared_examples 'Endpoint not found if read_model_registry not available' do
context 'when read_model_registry disabled for current project' do
before do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?)
.with(user, :read_model_registry, project)
.and_return(false)
end
it "is not found" do
is_expected.to have_gitlab_http_status(:not_found)
end
end
end
RSpec.shared_examples 'creates model experiments package files' do
it 'creates package files', :aggregate_failures do
expect { api_response }
.to change { project.packages.count }.by(1)
.and change { Packages::PackageFile.count }.by(1)
expect(api_response).to have_gitlab_http_status(:created)
package_file = project.packages.last.package_files.reload.last
expect(package_file.file_name).to eq(file_name)
end
it 'returns bad request if package creation fails' do
allow_next_instance_of(::Packages::MlModel::CreatePackageFileService) do |instance|
expect(instance).to receive(:execute).and_return(nil)
end
expect(api_response).to have_gitlab_http_status(:bad_request)
end
context 'when file is too large' do
it 'is bad request', :aggregate_failures do
allow_next_instance_of(UploadedFile) do |uploaded_file|
allow(uploaded_file).to receive(:size).and_return(project.actual_limits.ml_model_max_file_size + 1)
end
expect(api_response).to have_gitlab_http_status(:bad_request)
end
end
end
RSpec.shared_examples 'process ml model package upload' do
context 'with object storage disabled' do
before do
stub_package_file_object_storage(enabled: false)
end
context 'without a file from workhorse' do
let(:send_rewritten_field) { false }
it_behaves_like 'returning response status', :bad_request
end
context 'with correct params' do
it_behaves_like 'package workhorse uploads'
it_behaves_like 'creates model experiments package files'
# To be reactivated with https://gitlab.com/gitlab-org/gitlab/-/issues/414270
# it_behaves_like 'a package tracking event', '::API::MlModelPackages', 'push_package'
end
end
context 'with object storage enabled' do
let(:tmp_object) do
fog_connection.directories.new(key: 'packages').files.create( # rubocop:disable Rails/SaveBang
key: "tmp/uploads/#{file_name}",
body: 'content'
)
end
let(:fog_file) { fog_to_uploaded_file(tmp_object) }
let(:params) { { file: fog_file, 'file.remote_id' => file_name } }
context 'and direct upload enabled' do
let(:fog_connection) do
stub_package_file_object_storage(direct_upload: true)
end
it_behaves_like 'creates model experiments package files'
['123123', '../../123123'].each do |remote_id|
context "with invalid remote_id: #{remote_id}" do
let(:params) do
{
file: fog_file,
'file.remote_id' => remote_id
}
end
it { is_expected.to have_gitlab_http_status(:forbidden) }
end
end
end
context 'and direct upload disabled' do
let(:fog_connection) do
stub_package_file_object_storage(direct_upload: false)
end
it_behaves_like 'creates model experiments package files'
end
end
end

View File

@ -0,0 +1,38 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'admin/application_settings/_ai_access.html.haml', feature_category: :code_suggestions do
let_it_be(:admin) { build_stubbed(:admin) }
let(:page) { Capybara::Node::Simple.new(rendered) }
before do
allow(::Gitlab).to receive(:org_or_com?).and_return(false) # Will not render partial for .com or .org
assign(:application_setting, application_setting)
allow(view).to receive(:current_user) { admin }
allow(view).to receive(:expanded).and_return(true)
end
context 'when ai_access_token is not set' do
let(:application_setting) { build(:application_setting) }
it 'renders an empty password field' do
render
expect(rendered).to have_field('Personal access token', type: 'password')
expect(page.find_field('Personal access token').value).to be_blank
end
end
context 'when ai_access_token is set' do
let(:application_setting) do
build(:application_setting, ai_access_token: 'ai_access_token',
instance_level_code_suggestions_enabled: true)
end
it 'renders masked password field' do
render
expect(rendered).to have_field('Enter new personal access token', type: 'password')
expect(page.find_field('Enter new personal access token').value).to eq(ApplicationSettingMaskedAttrs::MASK)
end
end
end

View File

@ -110,4 +110,30 @@ RSpec.describe 'admin/application_settings/general.html.haml' do
end
end
end
describe 'instance-level code suggestions settings', feature_category: :code_suggestions do
before do
allow(::Gitlab).to receive(:org_or_com?).and_return(gitlab_org_or_com?)
render
end
context 'when on .com or .org' do
let(:gitlab_org_or_com?) { true }
it 'does not render the form' do
expect(rendered).not_to have_field('application_setting_instance_level_code_suggestions_enabled')
expect(rendered).not_to have_field('application_setting_ai_access_token')
end
end
context 'when not on .com and not on .org' do
let(:gitlab_org_or_com?) { false }
it 'renders the form' do
expect(rendered).to have_field('application_setting_instance_level_code_suggestions_enabled')
expect(rendered).to have_field('application_setting_ai_access_token')
end
end
end
end

View File

@ -279,6 +279,9 @@ func configureRoutes(u *upstream) {
// Generic Packages Repository
u.route("PUT", apiProjectPattern+`/packages/generic/`, requestBodyUploader),
// Ml Model Packages Repository
u.route("PUT", apiProjectPattern+`/packages/ml_models/`, requestBodyUploader),
// NuGet Artifact Repository
u.route("PUT", apiProjectPattern+`/packages/nuget/`, mimeMultipartUploader),

View File

@ -580,6 +580,7 @@ func TestPackageFilesUpload(t *testing.T) {
{"PUT", "/api/v4/projects/group%2Fproject/packages/conan/v1/files"},
{"PUT", "/api/v4/projects/group%2Fproject/packages/maven/v1/files"},
{"PUT", "/api/v4/projects/group%2Fproject/packages/generic/mypackage/0.0.1/myfile.tar.gz"},
{"PUT", "/api/v4/projects/group%2Fproject/packages/ml_models/mymodel/0.0.1/myfile.tar.gz"},
{"PUT", "/api/v4/projects/group%2Fproject/packages/debian/libsample0_1.2.3~alpha2-1_amd64.deb"},
{"POST", "/api/v4/projects/group%2Fproject/packages/rubygems/api/v1/gems/sample.gem"},
{"POST", "/api/v4/projects/group%2Fproject/packages/rpm/sample-4.23.fc21.x86_64.rpm"},