Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-06-01 12:09:17 +00:00
parent 7c42073320
commit 875662ef7b
25 changed files with 284 additions and 122 deletions

View File

@ -77,7 +77,7 @@ review-build-cng:
variables:
HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}"
DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}"
GITLAB_HELM_CHART_REF: "41d7632d9eba84f5816d808b98ccf3f5623e9fb5"
GITLAB_HELM_CHART_REF: "a6a609a19166f00b1a7774374041cd38a9f7e20d"
environment:
name: review/${CI_COMMIT_REF_SLUG}${FREQUENCY}
url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}

View File

@ -963,7 +963,7 @@ GEM
pyu-ruby-sasl (0.0.3.3)
raabro (1.1.6)
racc (1.6.0)
rack (2.2.3)
rack (2.2.3.1)
rack-accept (0.4.5)
rack (>= 0.4)
rack-attack (6.3.0)

View File

@ -1,7 +1,5 @@
import { s__ } from '~/locale';
export const PLATFORMS_WITHOUT_ARCHITECTURES = ['docker', 'kubernetes'];
export const REGISTRATION_TOKEN_PLACEHOLDER = '$REGISTRATION_TOKEN';
export const INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES = {

View File

@ -17,7 +17,6 @@ import { __, s__ } from '~/locale';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
import {
INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES,
PLATFORMS_WITHOUT_ARCHITECTURES,
REGISTRATION_TOKEN_PLACEHOLDER,
} from './constants';
import getRunnerPlatformsQuery from './graphql/queries/get_runner_platforms.query.graphql';
@ -60,20 +59,20 @@ export default {
platforms: {
query: getRunnerPlatformsQuery,
update(data) {
return data?.runnerPlatforms?.nodes.map(({ name, humanReadableName, architectures }) => {
return {
name,
humanReadableName,
architectures: architectures?.nodes || [],
};
});
return (
data?.runnerPlatforms?.nodes.map(({ name, humanReadableName, architectures }) => {
return {
name,
humanReadableName,
architectures: architectures?.nodes || [],
};
}) ?? []
);
},
result() {
if (this.platforms.length) {
// If it is set and available, select the defaultSelectedPlatform.
// Otherwise, select the first available platform
this.selectPlatform(this.defaultPlatform() || this.platforms[0]);
}
// If it is set and available, select the defaultSelectedPlatform.
// Otherwise, select the first available platform
this.selectPlatform(this.defaultPlatformName || this.platforms?.[0].name);
},
error() {
this.toggleAlert(true);
@ -86,8 +85,8 @@ export default {
},
variables() {
return {
platform: this.selectedPlatformName,
architecture: this.selectedArchitectureName || '',
platform: this.selectedPlatform,
architecture: this.selectedArchitecture || '',
};
},
update(data) {
@ -109,26 +108,21 @@ export default {
};
},
computed: {
platformsEmpty() {
return isEmpty(this.platforms);
},
instructionsEmpty() {
return isEmpty(this.instructions);
},
selectedPlatformName() {
return this.selectedPlatform?.name;
architectures() {
return this.platforms.find(({ name }) => name === this.selectedPlatform)?.architectures || [];
},
selectedArchitectureName() {
return this.selectedArchitecture?.name;
},
hasArchitecureList() {
return !PLATFORMS_WITHOUT_ARCHITECTURES.includes(this.selectedPlatformName);
binaryUrl() {
return this.architectures.find(({ name }) => name === this.selectedArchitecture)
?.downloadLocation;
},
instructionsWithoutArchitecture() {
return INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES[this.selectedPlatformName]?.instructions;
return INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES[this.selectedPlatform]?.instructions;
},
runnerInstallationLink() {
return INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES[this.selectedPlatformName]?.link;
return INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES[this.selectedPlatform]?.link;
},
registerInstructionsWithToken() {
const { registerInstructions } = this.instructions || {};
@ -139,7 +133,6 @@ export default {
this.registrationToken,
);
}
return registerInstructions;
},
},
@ -150,21 +143,17 @@ export default {
focusSelected() {
// By default the first platform always gets the focus, but when the `defaultPlatformName`
// property is present, any other platform might actually be selected.
this.$refs[this.selectedPlatformName]?.[0].$el.focus();
this.$refs[this.selectedPlatform]?.[0].$el.focus();
},
defaultPlatform() {
return this.platforms.find((platform) => platform.name === this.defaultPlatformName);
},
selectPlatform(platform) {
this.selectedPlatform = platform;
selectPlatform(platformName) {
this.selectedPlatform = platformName;
// Update architecture when platform changes
const architectures = platform.architectures || [];
const arch = architectures.find(({ name }) => name === this.selectedArchitectureName);
const arch = this.architectures.find(({ name }) => name === this.selectedArchitecture);
if (arch) {
this.selectArchitecture(arch);
this.selectArchitecture(arch.name);
} else {
this.selectArchitecture(architectures[0]);
this.selectArchitecture(this.architectures[0]?.name);
}
},
selectArchitecture(architecture) {
@ -210,9 +199,9 @@ export default {
{{ $options.i18n.fetchError }}
</gl-alert>
<gl-skeleton-loader v-if="platformsEmpty && $apollo.loading" />
<gl-skeleton-loader v-if="!platforms.length && $apollo.loading" />
<template v-if="!platformsEmpty">
<template v-if="platforms.length">
<h5>
{{ __('Environment') }}
</h5>
@ -227,29 +216,29 @@ export default {
v-for="platform in platforms"
:key="platform.name"
:ref="platform.name"
:selected="selectedPlatformName === platform.name"
@click="selectPlatform(platform)"
:selected="selectedPlatform === platform.name"
@click="selectPlatform(platform.name)"
>
{{ platform.humanReadableName }}
</gl-button>
</gl-button-group>
</div>
</template>
<template v-if="hasArchitecureList">
<template v-if="architectures.length">
<template v-if="selectedPlatform">
<h5>
{{ $options.i18n.architecture }}
<gl-loading-icon v-if="$apollo.loading" size="sm" inline />
</h5>
<gl-dropdown class="gl-mb-3" :text="selectedArchitectureName">
<gl-dropdown class="gl-mb-3" :text="selectedArchitecture">
<gl-dropdown-item
v-for="architecture in selectedPlatform.architectures"
v-for="architecture in architectures"
:key="architecture.name"
:is-check-item="true"
:is-checked="selectedArchitectureName === architecture.name"
:is-checked="selectedArchitecture === architecture.name"
data-testid="architecture-dropdown-item"
@click="selectArchitecture(architecture)"
@click="selectArchitecture(architecture.name)"
>
{{ architecture.name }}
</gl-dropdown-item>
@ -257,8 +246,9 @@ export default {
<div class="gl-sm-display-flex gl-align-items-center gl-mb-3">
<h5>{{ $options.i18n.downloadInstallBinary }}</h5>
<gl-button
v-if="binaryUrl"
class="gl-ml-auto"
:href="selectedArchitecture.downloadLocation"
:href="binaryUrl"
download
icon="download"
data-testid="binary-download-button"

View File

@ -112,13 +112,13 @@ class Projects::CompareController < Projects::ApplicationController
end
def start_ref
@start_ref ||= Addressable::URI.unescape(compare_params[:from])
@start_ref ||= Addressable::URI.unescape(compare_params[:from]).presence
end
def head_ref
return @ref if defined?(@ref)
@ref = @head_ref = Addressable::URI.unescape(compare_params[:to])
@ref = @head_ref = Addressable::URI.unescape(compare_params[:to]).presence
end
def define_commits

View File

@ -9,6 +9,10 @@
- base_domain_path = help_page_path('user/project/clusters/gitlab_managed_clusters', anchor: 'base-domain')
- base_domain_link_start = link_start % { url: base_domain_path }
- help_link_continouos = link_to sprite_icon('question-o'), help_page_path('topics/autodevops/stages.md', anchor: 'auto-deploy'), target: '_blank', rel: 'noopener noreferrer'
- help_link_timed = link_to sprite_icon('question-o'), help_page_path('topics/autodevops/customize.md', anchor: 'timed-incremental-rollout-to-production'), target: '_blank', rel: 'noopener noreferrer'
- help_link_incremental = link_to sprite_icon('question-o'), help_page_path('topics/autodevops/customize.md', anchor: 'incremental-rollout-to-production'), target: '_blank', rel: 'noopener noreferrer'
.row
.col-lg-12
= gitlab_ui_form_for @project, url: project_settings_ci_cd_path(@project, anchor: 'autodevops-settings') do |f|
@ -33,22 +37,8 @@
= s_('CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work.').html_safe % { base_domain_link_start: base_domain_link_start, kubernetes_cluster_link_start: kubernetes_cluster_link_start, link_end: link_end }
%label.gl-mt-3
%strong= s_('CICD|Deployment strategy')
.form-check
= form.radio_button :deploy_strategy, 'continuous', class: 'form-check-input'
= form.label :deploy_strategy_continuous, class: 'form-check-label' do
= s_('CICD|Continuous deployment to production')
= link_to sprite_icon('question-o'), help_page_path('topics/autodevops/stages.md', anchor: 'auto-deploy'), target: '_blank', rel: 'noopener noreferrer'
.form-check
= form.radio_button :deploy_strategy, 'timed_incremental', class: 'form-check-input'
= form.label :deploy_strategy_timed_incremental, class: 'form-check-label' do
= s_('CICD|Continuous deployment to production using timed incremental rollout')
= link_to sprite_icon('question-o'), help_page_path('topics/autodevops/customize.md', anchor: 'timed-incremental-rollout-to-production'), target: '_blank', rel: 'noopener noreferrer'
.form-check
= form.radio_button :deploy_strategy, 'manual', class: 'form-check-input'
= form.label :deploy_strategy_manual, class: 'form-check-label' do
= s_('CICD|Automatic deployment to staging, manual deployment to production')
= link_to sprite_icon('question-o'), help_page_path('topics/autodevops/customize.md', anchor: 'incremental-rollout-to-production'), target: '_blank', rel: 'noopener noreferrer'
= form.gitlab_ui_radio_component :deploy_strategy, 'continuous', (s_('CICD|Continuous deployment to production') + ' ' + help_link_continouos).html_safe
= form.gitlab_ui_radio_component :deploy_strategy, 'timed_incremental', (s_('CICD|Continuous deployment to production using timed incremental rollout') + ' ' + help_link_timed).html_safe
= form.gitlab_ui_radio_component :deploy_strategy, 'manual', (s_('CICD|Automatic deployment to staging, manual deployment to production') + ' ' + help_link_incremental).html_safe
= f.submit _('Save changes'), class: "btn gl-button btn-confirm gl-mt-5", data: { qa_selector: 'save_changes_button' }

View File

@ -37,11 +37,8 @@
data: { placeholder: _('Select branch'), endpoint: refs_project_path(@project, sort: 'updated_desc', find: 'branches') }})
- if source_level < target_level
.gl-alert.gl-alert-warning.gl-alert-not-dismissible.gl-max-content.gl-mt-4
.gl-alert-container
.gl-alert-content{ role: 'alert' }
= sprite_icon('warning', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
.gl-alert-body
= visibilityMismatchString
%br
= _('Review the target project before submitting to avoid exposing %{source} changes.') % { source: source_visibility }
= render Pajamas::AlertComponent.new(variant: :warning, dismissible: false, alert_class: 'gl-mb-4') do |c|
= c.body do
= visibilityMismatchString
%br
= _('Review the target project before submitting to avoid exposing %{source} changes.') % { source: source_visibility }

View File

@ -855,8 +855,8 @@ if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then
++ CI_SERVER_PROTOCOL=https
++ export CI_SERVER_NAME=GitLab
++ CI_SERVER_NAME=GitLab
++ export GITLAB_FEATURES=audit_events,burndown_charts,code_owners,contribution_analytics,description_diffs,elastic_search,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_weights,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,protected_refs_for_users,push_rules,related_issues,repository_mirrors,repository_size_limit,scoped_issue_board,usage_quotas,visual_review_app,wip_limits,adjourned_deletion_for_projects_and_groups,admin_audit_log,auditor_user,batch_comments,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,cluster_deployments,code_analytics,code_owner_approval_required,commit_committer_check,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,custom_prometheus_metrics,cycle_analytics_for_groups,db_load_balancing,default_project_deletion_protection,dependency_proxy,deploy_board,design_management,email_additional_text,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,github_project_service_integration,group_allowed_email_domains,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,merge_trains,metrics_reports,multiple_approval_rules,multiple_group_issue_boards,object_storage,operations_dashboard,packages,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,service_desk,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,container_scanning,dast,dependency_scanning,epics,group_ip_restriction,incident_management,insights,license_management,personal_access_token_expiration_policy,pod_logs,prometheus_alerts,report_approver_rules,sast,security_dashboard,tracing,web_ide_terminal
++ GITLAB_FEATURES=audit_events,burndown_charts,code_owners,contribution_analytics,description_diffs,elastic_search,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_weights,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,protected_refs_for_users,push_rules,related_issues,repository_mirrors,repository_size_limit,scoped_issue_board,usage_quotas,visual_review_app,wip_limits,adjourned_deletion_for_projects_and_groups,admin_audit_log,auditor_user,batch_comments,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,cluster_deployments,code_analytics,code_owner_approval_required,commit_committer_check,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,custom_prometheus_metrics,cycle_analytics_for_groups,db_load_balancing,default_project_deletion_protection,dependency_proxy,deploy_board,design_management,email_additional_text,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,github_project_service_integration,group_allowed_email_domains,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,merge_trains,metrics_reports,multiple_approval_rules,multiple_group_issue_boards,object_storage,operations_dashboard,packages,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,service_desk,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,cluster_health,container_scanning,dast,dependency_scanning,epics,group_ip_restriction,incident_management,insights,license_management,personal_access_token_expiration_policy,pod_logs,prometheus_alerts,report_approver_rules,sast,security_dashboard,tracing,web_ide_terminal
++ export GITLAB_FEATURES=audit_events,burndown_charts,code_owners,contribution_analytics,description_diffs,elastic_search,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_weights,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,protected_refs_for_users,push_rules,related_issues,repository_mirrors,repository_size_limit,scoped_issue_board,usage_quotas,visual_review_app,wip_limits,adjourned_deletion_for_projects_and_groups,admin_audit_log,auditor_user,batch_comments,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,cluster_deployments,code_analytics,code_owner_approval_required,commit_committer_check,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,custom_prometheus_metrics,cycle_analytics_for_groups,db_load_balancing,default_project_deletion_protection,dependency_proxy,deploy_board,design_management,email_additional_text,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,github_integration,group_allowed_email_domains,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,merge_trains,metrics_reports,multiple_approval_rules,multiple_group_issue_boards,object_storage,operations_dashboard,packages,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,service_desk,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,container_scanning,dast,dependency_scanning,epics,group_ip_restriction,incident_management,insights,license_management,personal_access_token_expiration_policy,pod_logs,prometheus_alerts,report_approver_rules,sast,security_dashboard,tracing,web_ide_terminal
++ GITLAB_FEATURES=audit_events,burndown_charts,code_owners,contribution_analytics,description_diffs,elastic_search,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_weights,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,protected_refs_for_users,push_rules,related_issues,repository_mirrors,repository_size_limit,scoped_issue_board,usage_quotas,visual_review_app,wip_limits,adjourned_deletion_for_projects_and_groups,admin_audit_log,auditor_user,batch_comments,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,cluster_deployments,code_analytics,code_owner_approval_required,commit_committer_check,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,custom_prometheus_metrics,cycle_analytics_for_groups,db_load_balancing,default_project_deletion_protection,dependency_proxy,deploy_board,design_management,email_additional_text,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,github_integration,group_allowed_email_domains,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,merge_trains,metrics_reports,multiple_approval_rules,multiple_group_issue_boards,object_storage,operations_dashboard,packages,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,service_desk,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,cluster_health,container_scanning,dast,dependency_scanning,epics,group_ip_restriction,incident_management,insights,license_management,personal_access_token_expiration_policy,pod_logs,prometheus_alerts,report_approver_rules,sast,security_dashboard,tracing,web_ide_terminal
++ export CI_PROJECT_ID=17893
++ CI_PROJECT_ID=17893
++ export CI_PROJECT_NAME=ci-debug-trace

View File

@ -3196,8 +3196,9 @@ job:
with the flags `File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_EXTGLOB`.
- For performance reasons, GitLab matches a maximum of 10,000 `exists` patterns or
file paths. After the 10,000th check, rules with patterned globs always match.
In other words, the `exists` rule always assumes a match in projects with more
than 10,000 files.
In other words, `exists` always reports `true` if more than 10,000 checks
run. Repositories with less than 10,000 files might still be impacted if the `exists`
rules are checked more than 10,000 times.
- `exists` resolves to `true` if any of the listed files are found (an `OR` operation).
#### `rules:allow_failure`

View File

@ -29,11 +29,11 @@ When the state of a flag changes (for example, disabled by default to enabled by
Possible version history entries are:
```markdown
> - [Introduced](issue-link) in GitLab X.X [with a flag](../../administration/feature_flags.md) named <flag name>. Disabled by default.
> - [Introduced](issue-link) in GitLab X.X [with a flag](../../administration/feature_flags.md) named `flag_name`. Disabled by default.
> - [Enabled on GitLab.com](issue-link) in GitLab X.X.
> - [Enabled on GitLab.com](issue-link) in GitLab X.X. Available to GitLab.com administrators only.
> - [Enabled on self-managed](issue-link) in GitLab X.X.
> - [Generally available](issue-link) in GitLab X.Y. [Feature flag <flag name>](issue-link) removed.
> - [Generally available](issue-link) in GitLab X.Y. [Feature flag `flag_name`](issue-link) removed.
```
You can combine entries if they happened in the same release:
@ -60,15 +60,15 @@ FLAG:
| If the feature is... | Use this text |
|--------------------------|---------------|
| Available | `On self-managed GitLab, by default this feature is available. To hide the feature, ask an administrator to [disable the feature flag](<path to>/administration/feature_flags.md) named <flag name>.` |
| Unavailable | `On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](<path to>/administration/feature_flags.md) named <flag name>.` |
| Available to some users | `On self-managed GitLab, by default this feature is available to a subset of users. To show or hide the feature for all, ask an administrator to [change the status of the feature flag](<path to>/administration/feature_flags.md) named <flag name>.` |
| Available, per-group | `On self-managed GitLab, by default this feature is available. To hide the feature per group, ask an administrator to [disable the feature flag](<path to>/administration/feature_flags.md) named <flag name>.` |
| Unavailable, per-group | `On self-managed GitLab, by default this feature is not available. To make it available per group, ask an administrator to [enable the feature flag](<path to>/administration/feature_flags.md) named <flag name>.` |
| Available, per-project | `On self-managed GitLab, by default this feature is available. To hide the feature per project or for your entire instance, ask an administrator to [disable the feature flag](<path to>/administration/feature_flags.md) named <flag name>.` |
| Unavailable, per-project | `On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, ask an administrator to [enable the feature flag](<path to>/administration/feature_flags.md) named <flag name>.` |
| Available, per-user | `On self-managed GitLab, by default this feature is available. To hide the feature per user, ask an administrator to [disable the feature flag](<path to>/administration/feature_flags.md) named <flag name>.` |
| Unavailable, per-user | `On self-managed GitLab, by default this feature is not available. To make it available per user, ask an administrator to [enable the feature flag](<path to>/administration/feature_flags.md) named <flag name>.` |
| Available | ``On self-managed GitLab, by default this feature is available. To hide the feature, ask an administrator to [disable the feature flag](<path to>/administration/feature_flags.md) named `flag_name`.`` |
| Unavailable | ``On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](<path to>/administration/feature_flags.md) named `flag_name`.`` |
| Available to some users | ``On self-managed GitLab, by default this feature is available to a subset of users. To show or hide the feature for all, ask an administrator to [change the status of the feature flag](<path to>/administration/feature_flags.md) named `flag_name`.`` |
| Available, per-group | ``On self-managed GitLab, by default this feature is available. To hide the feature per group, ask an administrator to [disable the feature flag](<path to>/administration/feature_flags.md) named `flag_name`.`` |
| Unavailable, per-group | ``On self-managed GitLab, by default this feature is not available. To make it available per group, ask an administrator to [enable the feature flag](<path to>/administration/feature_flags.md) named `flag_name`.`` |
| Available, per-project | ``On self-managed GitLab, by default this feature is available. To hide the feature per project or for your entire instance, ask an administrator to [disable the feature flag](<path to>/administration/feature_flags.md) named `flag_name`.`` |
| Unavailable, per-project | ``On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, ask an administrator to [enable the feature flag](<path to>/administration/feature_flags.md) named `flag_name`.`` |
| Available, per-user | ``On self-managed GitLab, by default this feature is available. To hide the feature per user, ask an administrator to [disable the feature flag](<path to>/administration/feature_flags.md) named `flag_name`.`` |
| Unavailable, per-user | ``On self-managed GitLab, by default this feature is not available. To make it available per user, ask an administrator to [enable the feature flag](<path to>/administration/feature_flags.md) named `flag_name`.`` |
### GitLab.com availability information
@ -114,5 +114,5 @@ And, when the feature is done and fully available to all users:
> - Introduced in GitLab 13.7 [with a flag](../../administration/feature_flags.md) named `forti_token_cloud`. Disabled by default.
> - [Enabled on self-managed](https://gitlab.com/issue/etc) in GitLab 13.8.
> - [Enabled on GitLab.com](https://gitlab.com/issue/etc) in GitLab 13.9.
> - [Generally available](issue-link) in GitLab 14.0. [Feature flag <flag name>](issue-link) removed.
> - [Generally available](issue-link) in GitLab 14.0. [Feature flag `forti_token_cloud`](issue-link) removed.
```

View File

@ -22,6 +22,7 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
| `:group_saml` | The test requires a GitLab instance that has SAML SSO enabled at the group level. Interacts with an external SAML identity provider. Paired with the `:orchestrated` tag. |
| `:instance_saml` | The test requires a GitLab instance that has SAML SSO enabled at the instance level. Interacts with an external SAML identity provider. Paired with the `:orchestrated` tag. |
| `:integrations` | This aims to test the available [integrations](../../../user/project/integrations/index.md#available-integrations). The test requires Docker to be installed in the run context. It will provision the containers and can be run against a local instance or using the `gitlab-qa` scenario `Test::Integration::Integrations` |
| `:issue`, `:issue_${num}` | Optional links to issues which might be related to the spec. Helps keep track of related issues and can also be used by tools that create test reports. Currently added automatically to `Allure` test report. Multiple tags can be used by adding an optional numeric suffix like `issue_1`, `issue_2` etc. |
| `:service_ping_disabled` | The test interacts with the GitLab configuration service ping at the instance level to turn Admin Area setting service ping checkbox on or off. This tag will have the test run only in the `service_ping_disabled` job and must be paired with the `:orchestrated` and `:requires_admin` tags. |
| `:jira` | The test requires a Jira Server. [GitLab-QA](https://gitlab.com/gitlab-org/gitlab-qa) provisions the Jira Server in a Docker container when the `Test::Integration::Jira` test scenario is run. |
| `:kubernetes` | The test includes a GitLab instance that is configured to be run behind an SSH tunnel, allowing a TLS-accessible GitLab. This test also includes provisioning of at least one Kubernetes cluster to test against. _This tag is often be paired with `:orchestrated`._ |
@ -42,6 +43,7 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
| `:requires_git_protocol_v2` | The test requires that Git protocol version 2 is enabled on the server. It's assumed to be enabled by default but if not the test can be skipped by setting `QA_CAN_TEST_GIT_PROTOCOL_V2` to `false`. |
| `:requires_praefect` | The test requires that the GitLab instance uses [Gitaly Cluster](../../../administration/gitaly/praefect.md) (a.k.a. Praefect) as the repository storage . It's assumed to be used by default but if not the test can be skipped by setting `QA_CAN_TEST_PRAEFECT` to `false`. |
| `:runner` | The test depends on and sets up a GitLab Runner instance, typically to run a pipeline. |
| `:sanity_feature_flags` | The test run in the `Test::Sanity::FeatureFlags` scenario to verify the functioning of the feature flag handling part of the test framework |
| `:skip_live_env` | The test is excluded when run against live deployed environments such as Staging, Canary, and Production. |
| `:skip_fips_env` | The test is excluded when run against an environment in FIPS mode. |
| `:skip_signup_disabled` | The test uses UI to sign up a new user and is skipped in any environment that does not allow new user registration via the UI. |
@ -49,4 +51,3 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
| `:smtp` | The test requires a GitLab instance to be configured to use an SMTP server. Tests SMTP notification email delivery from GitLab by using MailHog. |
| `:testcase` | The link to the test case issue in the [GitLab Project Test Cases](https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases). |
| `:transient` | The test tests transient bugs. It is excluded by default. |
| `:issue`, `:issue_${num}` | Optional links to issues which might be related to the spec. Helps keep track of related issues and can also be used by tools that create test reports. Currently added automatically to `Allure` test report. Multiple tags can be used by adding an optional numeric suffix like `issue_1`, `issue_2` etc. |

View File

@ -160,6 +160,7 @@ the related documentation.
| Maximum test cases per [unit test report](../../ci/testing/unit_test_reports.md) | `500000` | Unlimited |
| Maximum registered runners | Free tier: `50` per-group / `50` per-project<br/>All paid tiers: `1000` per-group / `1000` per-project | See [Number of registered runners per scope](../../administration/instance_limits.md#number-of-registered-runners-per-scope) |
| Limit of dotenv variables | Free tier: `50` / Premium tier: `100` / Ultimate tier: `150` | See [Limit dotenv variables](../../administration/instance_limits.md#limit-dotenv-variables) |
| Authorization token duration (minutes) | `15` | To set a custom value, in the Rails console, run `ApplicationSetting.last.update(container_registry_token_expire_delay: <integer>)`, where `<integer>` is the desired number of minutes. |
## Package registry limits

View File

@ -251,7 +251,7 @@ GEM
pry (~> 0.10)
public_suffix (4.0.6)
racc (1.6.0)
rack (2.2.3)
rack (2.2.3.1)
rack-test (1.1.0)
rack (>= 1.0, < 3)
rainbow (3.0.0)

View File

@ -9,6 +9,8 @@ module QA
AuthorizationError = Class.new(RuntimeError)
UnknownScopeError = Class.new(RuntimeError)
UnknownStateError = Class.new(RuntimeError)
UnknownFeatureFlagError = Class.new(RuntimeError)
DefinitionFileError = Class.new(RuntimeError)
class << self
# Documentation: https://docs.gitlab.com/ee/api/features.html
@ -52,7 +54,21 @@ module QA
def enabled?(key, **scopes)
feature = JSON.parse(get_features).find { |flag| flag['name'] == key.to_s }
feature && (feature['state'] == 'on' || feature['state'] == 'conditional' && scopes.present? && enabled_scope?(feature['gates'], **scopes))
if feature
feature['state'] == 'on' ||
feature['state'] == 'conditional' && scopes.present? && enabled_scope?(feature['gates'], **scopes)
else
# The feature wasn't found via the API so we check for a default value.
file = Pathname.new('../config/feature_flags')
.expand_path(Runtime::Path.qa_root)
.glob("**/#{key}.yml")
.first
raise UnknownFeatureFlagError, "No feature flag found named '#{key}'" unless file
definition = YAML.safe_load(File.read(file))
definition['default_enabled'].to_s.casecmp('true') == 0
end
end
private

View File

@ -0,0 +1,71 @@
# frozen_string_literal: true
module QA
RSpec.describe 'Feature flag handler sanity checks', :sanity_feature_flags do
context 'with an existing feature flag definition file' do
let(:definition) do
path = Pathname.new('../config/feature_flags')
.expand_path(Runtime::Path.qa_root)
.glob('**/*.yml')
.first
YAML.safe_load(File.read(path))
end
it 'reads the correct default enabled state' do
# This test will fail if we ever remove all the feature flags, but that's very unlikely given how many there
# are and how much we rely on them.
expect(QA::Runtime::Feature.enabled?(definition['name'])).to be definition['default_enabled']
end
end
describe 'feature flag definition files' do
let(:file) do
path = Pathname.new('../config/feature_flags/development').expand_path(Runtime::Path.qa_root)
Tempfile.new(%w[ff-test .yml], path)
end
let(:flag) { Pathname.new(file.path).basename('.yml').to_s }
before do
definition = <<~YAML
name: #{flag}
type: development
default_enabled: #{flag_enabled}
YAML
File.write(file, definition)
end
after do
file.close!
end
context 'with a default disabled feature flag' do
let(:flag_enabled) { 'false' }
it 'reads the flag as disabled' do
expect(QA::Runtime::Feature.enabled?(flag)).to be false
end
it 'reads as enabled after the flag is enabled' do
QA::Runtime::Feature.enable(flag)
expect(QA::Runtime::Feature.enabled?(flag)).to be true
end
end
context 'with a default enabled feature flag' do
let(:flag_enabled) { 'true' }
it 'reads the flag as enabled' do
expect(QA::Runtime::Feature.enabled?(flag)).to be true
end
it 'reads as disabled after the flag is disabled' do
QA::Runtime::Feature.disable(flag)
expect(QA::Runtime::Feature.enabled?(flag)).to be false
end
end
end
end
end

View File

@ -12,6 +12,7 @@ module QA
DEFAULT_TEST_PATH_ARGS = ['--', File.expand_path('./features', __dir__)].freeze
DEFAULT_STD_ARGS = [$stderr, $stdout].freeze
DEFAULT_SKIPPED_TAGS = %w[orchestrated transient sanity_feature_flags].freeze
def initialize
@tty = false
@ -25,7 +26,7 @@ module QA
if tags.any?
tags.each { |tag| tags_for_rspec.push(['--tag', tag.to_s]) }
else
tags_for_rspec.push(%w[--tag ~orchestrated --tag ~transient]) unless (%w[-t --tag] & options).any?
tags_for_rspec.push(DEFAULT_SKIPPED_TAGS.map { |tag| %W[--tag ~#{tag}] }) unless (%w[-t --tag] & options).any?
end
tags_for_rspec.push(%w[--tag ~geo]) unless QA::Runtime::Env.geo_environment?

View File

@ -61,7 +61,7 @@ RSpec.describe QA::Runtime::Feature do
.to receive(:get)
.and_return(Struct.new(:code, :body).new(200, %Q([{ "name": "a_flag", "state": "conditional", "gates": #{gates} }])))
expect(described_class.enabled?(feature_flag, scope => actor)).to be_truthy
expect(described_class.enabled?(feature_flag, scope => actor)).to be true
end
end
end
@ -172,7 +172,7 @@ RSpec.describe QA::Runtime::Feature do
.to receive(:get)
.and_return(Struct.new(:code, :body).new(200, '[{ "name": "a_flag", "state": "on" }]'))
expect(described_class.enabled?(feature_flag)).to be_truthy
expect(described_class.enabled?(feature_flag)).to be true
end
it 'raises an error when the scope is unknown' do
@ -224,6 +224,75 @@ RSpec.describe QA::Runtime::Feature do
let(:gates) { %q([{"key": "groups", "value": ["foo"]}]) }
end
end
context 'when a feature flag is not found via the API and there is no definition file' do
before do
allow(QA::Runtime::API::Request)
.to receive(:new)
.with(api_client, "/features")
.and_return(request)
allow(described_class)
.to receive(:get)
.and_return(Struct.new(:code, :body).new(200, '[]'))
allow(Dir).to receive(:glob).and_return([])
end
it 'raises an error' do
expect { described_class.enabled?(feature_flag) }
.to raise_error(QA::Runtime::Feature::UnknownFeatureFlagError)
end
end
context 'with definition files' do
context 'when no features are found via the API' do
before do
allow(QA::Runtime::API::Request)
.to receive(:new)
.with(api_client, "/features")
.and_return(request)
allow(described_class)
.to receive(:get)
.and_return(Struct.new(:code, :body).new(200, '[]'))
allow(Dir).to receive(:glob).and_return(['file_path'])
allow(File).to receive(:read).and_return(definition)
end
context 'with a default enabled defintion' do
let(:definition) { 'default_enabled: true' }
it 'returns a default enabled flag' do
expect(described_class.enabled?(feature_flag)).to be true
end
end
context 'with a default disabled defintion' do
let(:definition) { 'default_enabled: false' }
it 'returns a default disabled flag' do
expect(described_class.enabled?(feature_flag)).to be false
end
end
end
context 'when the feature is found via the API' do
before do
allow(QA::Runtime::API::Request)
.to receive(:new)
.with(api_client, "/features")
.and_return(request)
allow(described_class)
.to receive(:get)
.and_return(Struct.new(:code, :body).new(200, '[{ "name": "a_flag", "state": "on" }]'))
end
it 'returns the value from the API not the definition file' do
expect(Dir).not_to receive(:glob)
expect(File).not_to receive(:read)
expect(described_class.enabled?(feature_flag)).to be true
end
end
end
end
end

View File

@ -1,14 +1,18 @@
# frozen_string_literal: true
RSpec.describe QA::Specs::Runner do
shared_examples 'excludes orchestrated, transient, and geo' do
it 'excludes the orchestrated, transient, and geo tags, and includes default args' do
expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~transient', '--tag', '~geo', *described_class::DEFAULT_TEST_PATH_ARGS])
shared_examples 'excludes default skipped, and geo' do
it 'excludes the default skipped and geo tags, and includes default args' do
expect_rspec_runner_arguments(DEFAULT_SKIPPED_TAGS + ['--tag', '~geo', *described_class::DEFAULT_TEST_PATH_ARGS])
subject.perform
end
end
before do
stub_const('DEFAULT_SKIPPED_TAGS', %w[--tag ~orchestrated --tag ~transient --tag ~sanity_feature_flags].freeze)
end
describe '#perform' do
before do
allow(QA::Runtime::Browser).to receive(:configure!)
@ -17,13 +21,15 @@ RSpec.describe QA::Specs::Runner do
QA::Runtime::Scenario.define(:klass, "QA::Scenario::Test::Instance::All")
end
it_behaves_like 'excludes orchestrated, transient, and geo'
it_behaves_like 'excludes default skipped, and geo'
context 'when tty is set' do
subject { described_class.new.tap { |runner| runner.tty = true } }
it 'sets the `--tty` flag' do
expect_rspec_runner_arguments(['--tty', '--tag', '~orchestrated', '--tag', '~transient', '--tag', '~geo', *described_class::DEFAULT_TEST_PATH_ARGS])
expect_rspec_runner_arguments(
['--tty'] + DEFAULT_SKIPPED_TAGS + ['--tag', '~geo', *described_class::DEFAULT_TEST_PATH_ARGS]
)
subject.perform
end
@ -39,7 +45,10 @@ RSpec.describe QA::Specs::Runner do
end
it 'sets the `--dry-run` flag' do
expect_rspec_runner_arguments(['--dry-run', '--tag', '~orchestrated', '--tag', '~transient', '--tag', '~geo', *described_class::DEFAULT_TEST_PATH_ARGS], [$stderr, anything])
expect_rspec_runner_arguments(
['--dry-run'] + DEFAULT_SKIPPED_TAGS + ['--tag', '~geo', *described_class::DEFAULT_TEST_PATH_ARGS],
[$stderr, anything]
)
subject.perform
end
@ -73,7 +82,10 @@ RSpec.describe QA::Specs::Runner do
subject { described_class.new.tap { |runner| runner.options = %w[--tag actioncable] } }
it 'includes the option value in the file name' do
expect_rspec_runner_arguments(['--dry-run', '--tag', '~geo', '--tag', 'actioncable', *described_class::DEFAULT_TEST_PATH_ARGS], [$stderr, anything])
expect_rspec_runner_arguments(
['--dry-run', '--tag', '~geo', '--tag', 'actioncable', *described_class::DEFAULT_TEST_PATH_ARGS],
[$stderr, anything]
)
expect(File).to receive(:open).with('no_of_examples/test_instance_all_actioncable.txt', 'w') { '22' }
@ -98,7 +110,10 @@ RSpec.describe QA::Specs::Runner do
end
it 'sets the `--dry-run` flag' do
expect_rspec_runner_arguments(['--dry-run', '--tag', '~orchestrated', '--tag', '~transient', '--tag', '~geo', *described_class::DEFAULT_TEST_PATH_ARGS], [$stderr, anything])
expect_rspec_runner_arguments(
['--dry-run'] + DEFAULT_SKIPPED_TAGS + ['--tag', '~geo', *described_class::DEFAULT_TEST_PATH_ARGS],
[$stderr, anything]
)
subject.perform
end
@ -125,7 +140,9 @@ RSpec.describe QA::Specs::Runner do
subject { described_class.new.tap { |runner| runner.tags = %i[orchestrated github] } }
it 'focuses on the given tags' do
expect_rspec_runner_arguments(['--tag', 'orchestrated', '--tag', 'github', '--tag', '~geo', *described_class::DEFAULT_TEST_PATH_ARGS])
expect_rspec_runner_arguments(
['--tag', 'orchestrated', '--tag', 'github', '--tag', '~geo', *described_class::DEFAULT_TEST_PATH_ARGS]
)
subject.perform
end
@ -144,8 +161,8 @@ RSpec.describe QA::Specs::Runner do
context 'when "qa/specs/features/foo" is set as options' do
subject { described_class.new.tap { |runner| runner.options = %w[qa/specs/features/foo] } }
it 'passes the given tests path and excludes the orchestrated, transient, and geo tags' do
expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~transient', '--tag', '~geo', 'qa/specs/features/foo'])
it 'passes the given tests path and excludes the default skipped, and geo tags' do
expect_rspec_runner_arguments(DEFAULT_SKIPPED_TAGS + ['--tag', '~geo', 'qa/specs/features/foo'])
subject.perform
end
@ -167,7 +184,7 @@ RSpec.describe QA::Specs::Runner do
end
it 'includes default args and excludes the skip_signup_disabled tag' do
expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~transient', '--tag', '~geo', '--tag', '~skip_signup_disabled', *described_class::DEFAULT_TEST_PATH_ARGS])
expect_rspec_runner_arguments(DEFAULT_SKIPPED_TAGS + ['--tag', '~geo', '--tag', '~skip_signup_disabled', *described_class::DEFAULT_TEST_PATH_ARGS])
subject.perform
end
@ -179,7 +196,7 @@ RSpec.describe QA::Specs::Runner do
end
it 'includes default args and excludes the skip_live_env tag' do
expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~transient', '--tag', '~geo', '--tag', '~skip_live_env', *described_class::DEFAULT_TEST_PATH_ARGS])
expect_rspec_runner_arguments(DEFAULT_SKIPPED_TAGS + ['--tag', '~geo', '--tag', '~skip_live_env', *described_class::DEFAULT_TEST_PATH_ARGS])
subject.perform
end
end
@ -212,7 +229,10 @@ RSpec.describe QA::Specs::Runner do
end
it 'includes default args and excludes all unsupported tags' do
expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~transient', '--tag', '~geo', *excluded_feature_tags_except(feature), *described_class::DEFAULT_TEST_PATH_ARGS])
expect_rspec_runner_arguments(
DEFAULT_SKIPPED_TAGS + ['--tag', '~geo', *excluded_feature_tags_except(feature),
*described_class::DEFAULT_TEST_PATH_ARGS]
)
subject.perform
end
@ -237,11 +257,11 @@ RSpec.describe QA::Specs::Runner do
end
end
it_behaves_like 'excludes orchestrated, transient, and geo'
it_behaves_like 'excludes default skipped, and geo'
end
context 'when features are not specified' do
it_behaves_like 'excludes orchestrated, transient, and geo'
it_behaves_like 'excludes default skipped, and geo'
end
end

View File

@ -248,7 +248,6 @@ function download_chart() {
helm repo add gitlab https://charts.gitlab.io
echoinfo "Building the gitlab chart's dependencies..."
helm dependency build "gitlab-${GITLAB_HELM_CHART_REF}"
}
function base_config_changed() {

View File

@ -44,6 +44,14 @@ RSpec.describe Projects::CompareController do
expect(response).to be_successful
end
end
context 'with missing parameters' do
let(:params) { super().merge(from: '', to: '') }
it 'returns successfully' do
expect(response).to be_successful
end
end
end
describe 'GET show' do

View File

@ -44,7 +44,7 @@ RSpec.describe Integrations::Campfire do
it "calls Campfire API to get a list of rooms and speak in a room" do
# make sure a valid list of rooms is returned
body = File.read(Rails.root + 'spec/fixtures/project_services/campfire/rooms.json')
body = File.read(Rails.root + 'spec/fixtures/integrations/campfire/rooms.json')
stub_full_request(@rooms_url).with(basic_auth: @auth).to_return(
body: body,
@ -65,7 +65,7 @@ RSpec.describe Integrations::Campfire do
it "calls Campfire API to get a list of rooms but shouldn't speak in a room" do
# return a list of rooms that do not contain a room named 'test-room'
body = File.read(Rails.root + 'spec/fixtures/project_services/campfire/rooms2.json')
body = File.read(Rails.root + 'spec/fixtures/integrations/campfire/rooms2.json')
stub_full_request(@rooms_url).with(basic_auth: @auth).to_return(
body: body,
status: 200,

View File

@ -44,7 +44,7 @@ Integration.available_integration_names.each do |integration|
let(:licensed_features) do
{
'github' => :github_project_service_integration
'github' => :github_integration
}
end

View File

@ -34,7 +34,7 @@ GEM
parallel (1.19.2)
parser (2.7.2.0)
ast (~> 2.4.1)
rack (2.2.3)
rack (2.2.3.1)
rainbow (3.0.0)
regexp_parser (1.8.2)
rexml (3.2.4)