Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-07-26 21:09:48 +00:00
parent cafc99870a
commit f57bd3d348
32 changed files with 254 additions and 105 deletions

View File

@ -491,7 +491,7 @@ group :test do
# Moved in `test` because https://gitlab.com/gitlab-org/gitlab/-/issues/217527
gem 'derailed_benchmarks', require: false
gem 'gitlab_quality-test_tooling', '~> 0.9.2', require: false
gem 'gitlab_quality-test_tooling', '~> 0.9.3', require: false
end
gem 'octokit', '~> 4.15'

View File

@ -218,7 +218,7 @@
{"name":"gitlab-styles","version":"10.1.0","platform":"ruby","checksum":"f42745f5397d042fe24cf2d0eb56c995b37f9f43d8fb79b834d197a1cafdc84a"},
{"name":"gitlab_chronic_duration","version":"0.10.6.2","platform":"ruby","checksum":"6dda4cfe7dca9b958f163ac8835c3d9cc70cf8df8cbb89bb2fbf9ba4375105fb"},
{"name":"gitlab_omniauth-ldap","version":"2.2.0","platform":"ruby","checksum":"bb4d20acb3b123ed654a8f6a47d3fac673ece7ed0b6992edb92dca14bad2838c"},
{"name":"gitlab_quality-test_tooling","version":"0.9.2","platform":"ruby","checksum":"bf9977c2ddc5603a6fdcb2c6bc7aba5c9eec548cd800dd791fb3d3aaaca4c70f"},
{"name":"gitlab_quality-test_tooling","version":"0.9.3","platform":"ruby","checksum":"9751f3504b717499588bd0fa5517de9b6756e8b9548777ea0283b889694580f0"},
{"name":"globalid","version":"1.1.0","platform":"ruby","checksum":"b337e1746f0c8cb0a6c918234b03a1ddeb4966206ce288fbb57779f59b2d154f"},
{"name":"gon","version":"6.4.0","platform":"ruby","checksum":"e3a618d659392890f1aa7db420f17c75fd7d35aeb5f8fe003697d02c4b88d2f0"},
{"name":"google-apis-androidpublisher_v3","version":"0.34.0","platform":"ruby","checksum":"d7e1d7dd92f79c498fe2082222a1740d788e022e660c135564b3fd299cab5425"},

View File

@ -675,7 +675,7 @@ GEM
omniauth (>= 1.3, < 3)
pyu-ruby-sasl (>= 0.0.3.3, < 0.1)
rubyntlm (~> 0.5)
gitlab_quality-test_tooling (0.9.2)
gitlab_quality-test_tooling (0.9.3)
activesupport (>= 6.1, < 7.1)
gitlab (~> 4.19)
http (~> 5.0)
@ -1826,7 +1826,7 @@ DEPENDENCIES
gitlab-utils!
gitlab_chronic_duration (~> 0.10.6.2)
gitlab_omniauth-ldap (~> 2.2.0)
gitlab_quality-test_tooling (~> 0.9.2)
gitlab_quality-test_tooling (~> 0.9.3)
gon (~> 6.4.0)
google-apis-androidpublisher_v3 (~> 0.34.0)
google-apis-cloudbilling_v1 (~> 0.21.0)

View File

@ -1,5 +1,5 @@
<script>
import { GlPagination } from '@gitlab/ui';
import { GlButton, GlCard, GlIcon, GlPagination } from '@gitlab/ui';
import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import { buildUrlWithCurrentLocation } from '~/lib/utils/common_utils';
import { createAlert, VARIANT_DANGER } from '~/alert';
@ -15,6 +15,9 @@ export default {
name: 'BroadcastMessagesBase',
NEW_BROADCAST_MESSAGE,
components: {
GlButton,
GlCard,
GlIcon,
GlPagination,
MessageForm,
MessagesTable,
@ -36,6 +39,10 @@ export default {
},
i18n: {
title: s__('BroadcastMessages|Messages'),
addTitle: s__('BroadcastMessages|Add new message'),
emptyMessage: s__('BroadcastMessages|No broadcast messages defined yet.'),
addButton: s__('BroadcastMessages|Add new message'),
deleteError: s__(
'BroadcastMessages|There was an issue deleting this message, please try again later.',
),
@ -49,6 +56,7 @@ export default {
...message,
disable_delete: false,
})),
showAddForm: false,
};
},
@ -75,7 +83,12 @@ export default {
buildPageUrl(newPage) {
return buildUrlWithCurrentLocation(`?page=${newPage}`);
},
toggleAddForm() {
this.showAddForm = !this.showAddForm;
},
closeAddForm() {
this.showAddForm = false;
},
async deleteMessage(messageId) {
const index = this.visibleMessages.findIndex((m) => m.id === messageId);
if (!index === -1) return;
@ -101,17 +114,48 @@ export default {
<template>
<div>
<message-form :broadcast-message="$options.NEW_BROADCAST_MESSAGE" />
<messages-table
v-if="hasVisibleMessages"
:messages="visibleMessages"
@delete-message="deleteMessage"
/>
<gl-card
class="gl-new-card"
header-class="gl-new-card-header"
body-class="gl-new-card-body gl-overflow-hidden gl-px-0"
>
<template #header>
<div class="gl-new-card-title-wrapper">
<h3 class="gl-new-card-title">{{ $options.i18n.title }}</h3>
<div class="gl-new-card-count">
<gl-icon name="messages" class="gl-mr-2" />
{{ messagesCount }}
</div>
</div>
<gl-button v-if="!showAddForm" size="small" @click="toggleAddForm">{{
$options.i18n.addButton
}}</gl-button>
</template>
<div v-if="showAddForm" class="gl-new-card-add-form gl-m-3">
<h4 class="gl-mt-0">{{ $options.i18n.addTitle }}</h4>
<message-form
:broadcast-message="$options.NEW_BROADCAST_MESSAGE"
@close-add-form="closeAddForm"
/>
</div>
<messages-table
v-if="hasVisibleMessages"
:messages="visibleMessages"
@delete-message="deleteMessage"
/>
<div v-else-if="!showAddForm" class="gl-new-card-empty gl-px-5 gl-py-4">
{{ $options.i18n.emptyMessage }}
</div>
</gl-card>
<gl-pagination
v-model="currentPage"
:total-items="totalMessages"
:link-gen="buildPageUrl"
align="center"
class="gl-mt-5"
/>
</div>
</template>

View File

@ -172,6 +172,9 @@ export default {
this.targetSelected = this.initialTarget();
},
methods: {
closeForm() {
this.$emit('close-add-form');
},
async onSubmit() {
this.loading = true;
@ -182,7 +185,6 @@ export default {
this.loading = false;
}
},
async submitForm() {
const requestMethod = this.isAddForm ? 'post' : 'patch';
@ -197,7 +199,6 @@ export default {
}
return true;
},
async renderPreview() {
try {
const res = await axios.post(this.previewPath, this.formPayload, FORM_HEADERS);
@ -206,7 +207,6 @@ export default {
this.renderedMessage = '';
}
},
initialTarget() {
if (this.targetAccessLevels.length > 0) {
return TARGET_ROLES;
@ -238,6 +238,7 @@ export default {
id="message-textarea"
v-model="message"
size="sm"
autofocus
:debounce="$options.DEFAULT_DEBOUNCE_AND_THROTTLE_MS"
:placeholder="$options.i18n.messagePlaceholder"
data-testid="message-input"
@ -329,7 +330,10 @@ export default {
>
{{ isAddForm ? $options.i18n.add : $options.i18n.update }}
</gl-button>
<gl-button v-if="!isAddForm" :href="messagesPath" data-testid="cancel-button">
<gl-button v-if="isAddForm" @click="closeForm">
{{ $options.i18n.cancel }}
</gl-button>
<gl-button v-else :href="messagesPath" data-testid="cancel-button">
{{ $options.i18n.cancel }}
</gl-button>
</div>

View File

@ -1,7 +1,7 @@
<script>
import { GlBroadcastMessage, GlButton, GlTableLite } from '@gitlab/ui';
import { GlBroadcastMessage, GlButton, GlTableLite, GlModal, GlModalDirective } from '@gitlab/ui';
import SafeHtml from '~/vue_shared/directives/safe_html';
import { __ } from '~/locale';
import { __, s__ } from '~/locale';
import { formatDate } from '~/lib/utils/datetime/date_format_utility';
const DEFAULT_TD_CLASSES = 'gl-vertical-align-middle!';
@ -12,13 +12,31 @@ export default {
GlBroadcastMessage,
GlButton,
GlTableLite,
GlModal,
},
directives: {
SafeHtml,
GlModal: GlModalDirective,
},
i18n: {
title: s__('BroadcastMessages|Delete broadcast message'),
edit: __('Edit'),
delete: __('Delete'),
modalMessage: s__('BroadcastMessages|Do you really want to delete this broadcast message?'),
},
modal: {
actionPrimary: {
text: s__('BroadcastMessages|Delete message'),
attributes: {
variant: 'danger',
},
},
actionSecondary: {
text: __('Cancel'),
attributes: {
variant: 'default',
},
},
},
props: {
messages: {
@ -81,6 +99,7 @@ export default {
:items="messages"
:fields="$options.fields"
:tbody-tr-attr="{ 'data-testid': 'message-row' }"
class="gl-mt-n1 gl-mb-n2"
stacked="md"
>
<template #cell(preview)="{ item: { message, theme, broadcast_type, dismissable } }">
@ -104,17 +123,25 @@ export default {
:href="edit_path"
data-testid="edit-message"
/>
<gl-button
v-gl-modal="`delete-message-${id}`"
class="gl-ml-3"
icon="remove"
variant="danger"
:aria-label="$options.i18n.delete"
rel="nofollow"
:disabled="disable_delete"
:data-testid="`delete-message-${id}`"
@click="$emit('delete-message', id)"
/>
<gl-modal
:title="$options.i18n.title"
:action-primary="$options.modal.actionPrimary"
:action-secondary="$options.modal.actionSecondary"
:modal-id="`delete-message-${id}`"
size="sm"
@primary="$emit('delete-message', id)"
>
{{ $options.i18n.modalMessage }}
</gl-modal>
</template>
</gl-table-lite>
</template>

View File

@ -80,8 +80,8 @@ export default {
projectPath: this.projectPath,
filePath: this.path,
ref: this.originalBranch || this.ref,
shouldFetchRawText: Boolean(this.glFeatures.highlightJs),
refType: this.refType?.toUpperCase() || null,
shouldFetchRawText: true,
};
return queryVariables;
@ -193,8 +193,7 @@ export default {
);
},
shouldLoadLegacyViewer() {
const isTextFile = this.viewer.fileType === TEXT_FILE_TYPE && !this.glFeatures.highlightJs;
return isTextFile || LEGACY_FILE_TYPES.includes(this.blobInfo.fileType) || this.useFallback;
return LEGACY_FILE_TYPES.includes(this.blobInfo.fileType) || this.useFallback;
},
legacyViewerLoaded() {
return (
@ -355,7 +354,7 @@ export default {
:active-viewer-type="viewer.type"
:has-render-error="hasRenderError"
:show-path="false"
:override-copy="glFeatures.highlightJs"
:override-copy="true"
@viewer-changed="handleViewerChanged"
@copy="onCopy"
>
@ -428,7 +427,7 @@ export default {
:code-navigation-path="blobInfo.codeNavigationPath"
:blob-path="blobInfo.path"
:path-prefix="blobInfo.projectBlobPathRoot"
:wrap-text-nodes="glFeatures.highlightJs"
:wrap-text-nodes="true"
/>
</div>
<ai-genie

View File

@ -16,7 +16,6 @@ import { buildURLwithRefType, joinPaths } from '~/lib/utils/url_utility';
import { TREE_PAGE_SIZE, ROW_APPEAR_DELAY } from '~/repository/constants';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import blobInfoQuery from 'shared_queries/repository/blob_info.query.graphql';
import getRefMixin from '../../mixins/get_ref';
@ -36,7 +35,7 @@ export default {
GlHoverLoad: GlHoverLoadDirective,
SafeHtml,
},
mixins: [getRefMixin, glFeatureFlagMixin()],
mixins: [getRefMixin],
inject: ['refType'],
props: {
commitInfo: {
@ -176,7 +175,7 @@ export default {
filePath: this.path,
ref: this.ref,
refType: this.refType?.toUpperCase() || null,
shouldFetchRawText: Boolean(this.glFeatures.highlightJs),
shouldFetchRawText: true,
});
},
apolloQuery(query, variables) {

View File

@ -90,11 +90,18 @@ export default {
: `git fetch origin\ngit checkout -b ${this.escapedSourceBranch} ${escapedOriginBranch}`; // eslint-disable-line @gitlab/require-i18n-strings
},
mergeInfo2() {
return `git push origin ${this.escapedSourceBranch}`; // eslint-disable-line @gitlab/require-i18n-strings
return this.isFork
? `git push "${this.sourceProjectDefaultUrl}" ${this.escapedForkPushBranch}` // eslint-disable-line @gitlab/require-i18n-strings
: `git push origin ${this.escapedSourceBranch}`; // eslint-disable-line @gitlab/require-i18n-strings
},
escapedForkBranch() {
return escapeShellString(`${this.sourceProjectPath}-${this.sourceBranch}`);
},
escapedForkPushBranch() {
return escapeShellString(
`${this.sourceProjectPath}-${this.sourceBranch}:${this.sourceBranch}`,
);
},
escapedSourceBranch() {
return escapeShellString(this.sourceBranch);
},

View File

@ -14,6 +14,8 @@
@include media-breakpoint-up(sm) {
display: flex;
flex-wrap: wrap;
gap: 8px;
.tree-ref-container {
flex: 1;
@ -24,7 +26,11 @@
.control {
float: left;
margin-left: 8px;
margin-right: 8px;
&:last-child {
margin-right: 0;
}
}
}

View File

@ -48,7 +48,6 @@ class Projects::BlobController < Projects::ApplicationController
urgency :low, [:create, :show, :edit, :update, :diff]
before_action do
push_frontend_feature_flag(:highlight_js, @project)
push_frontend_feature_flag(:highlight_js_worker, @project)
push_frontend_feature_flag(:explain_code_chat, current_user)
push_licensed_feature(:file_locks) if @project.licensed_feature_available?(:file_locks)

View File

@ -18,7 +18,6 @@ class Projects::TreeController < Projects::ApplicationController
before_action :authorize_edit_tree!, only: [:create_dir]
before_action do
push_frontend_feature_flag(:highlight_js, @project)
push_frontend_feature_flag(:highlight_js_worker, @project)
push_frontend_feature_flag(:explain_code_chat, current_user)
push_licensed_feature(:file_locks) if @project.licensed_feature_available?(:file_locks)

View File

@ -37,7 +37,6 @@ class ProjectsController < Projects::ApplicationController
before_action :check_export_rate_limit!, only: [:export, :download_export, :generate_new_export]
before_action do
push_frontend_feature_flag(:highlight_js, @project)
push_frontend_feature_flag(:highlight_js_worker, @project)
push_frontend_feature_flag(:remove_monitor_metrics, @project)
push_frontend_feature_flag(:explain_code_chat, current_user)

View File

@ -1,8 +0,0 @@
---
name: highlight_js
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75005
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346257
milestone: '14.6'
type: development
group: group::source code
default_enabled: true

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
class IndexProjectIdAndPackageManagerForSbomOccurrences < Gitlab::Database::Migration[2.1]
INDEX_NAME = 'index_sbom_occurrences_on_project_id_and_package_manager'
disable_ddl_transaction!
def up
add_concurrent_index :sbom_occurrences, [:project_id, :package_manager], name: INDEX_NAME
end
def down
remove_concurrent_index_by_name :sbom_occurrences, INDEX_NAME
end
end

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
class IndexProjectIdComponentIdAndIdForSbomOccurrences < Gitlab::Database::Migration[2.1]
INDEX_NAME = 'index_sbom_occurrences_on_project_id_and_component_id_and_id'
disable_ddl_transaction!
def up
add_concurrent_index :sbom_occurrences, [:project_id, :component_id, :id], name: INDEX_NAME
end
def down
remove_concurrent_index_by_name :sbom_occurrences, INDEX_NAME
end
end

View File

@ -0,0 +1 @@
93f43b785d2f0454089fdb8dcd214205596232c765a652bb3588d90a3f6ae040

View File

@ -0,0 +1 @@
7d6de45ae45840d1743290b4f32fb1f37482a0bd7ac689122b2021c5edabc599

View File

@ -32981,8 +32981,12 @@ CREATE INDEX index_sbom_occurrences_on_pipeline_id ON sbom_occurrences USING btr
CREATE INDEX index_sbom_occurrences_on_project_id ON sbom_occurrences USING btree (project_id);
CREATE INDEX index_sbom_occurrences_on_project_id_and_component_id_and_id ON sbom_occurrences USING btree (project_id, component_id, id);
CREATE INDEX index_sbom_occurrences_on_project_id_and_id ON sbom_occurrences USING btree (project_id, id);
CREATE INDEX index_sbom_occurrences_on_project_id_and_package_manager ON sbom_occurrences USING btree (project_id, package_manager);
CREATE INDEX index_sbom_occurrences_on_project_id_component_id ON sbom_occurrences USING btree (project_id, component_id);
CREATE INDEX index_sbom_occurrences_on_source_id ON sbom_occurrences USING btree (source_id);

View File

@ -164,7 +164,7 @@ Make sure the AWS KMS keys are replicated to your desired primary, secondary and
To enable the Inbound Private Link:
1. In the body of your [support ticket](#configuration-changes), include the IAM Principal for the AWS user or role in your own AWS Organization that's establishing the VPC endpoint in your AWS account. GitLab Dedicated uses this IAM Principal for access-control. This IAM principal is the only one able to set up an endpoint to the service.
1. In the body of your [support ticket](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=4414917877650), include the IAM Principal for the AWS user or role in your own AWS Organization that's establishing the VPC endpoint in your AWS account. GitLab Dedicated uses this IAM Principal for access-control. This IAM principal is the only one able to set up an endpoint to the service.
1. After your IAM Principal has been allowlisted, GitLab [creates the Endpoint Service](https://docs.aws.amazon.com/vpc/latest/privatelink/create-endpoint-service.html) and communicates the `Service Endpoint Name` on the support ticket. The service name is generated by AWS upon creation of the service endpoint.
- GitLab handles the domain verification for the Private DNS name, so that DNS resolution of the tenant instance domain name in your VPC resolves to the PrivateLink endpoint.
- GitLab makes the Endpoint Service available in the Availability Zones you specified during the initial onboarding. If you did not specify any Availability Zones, GitLab randomly selects the Availability Zones IDs.
@ -181,8 +181,8 @@ Outbound Private Links allow the GitLab Dedicated instance to securely communica
To enable an Outbound Private Link:
1. In your [support ticket](#configuration-changes), GitLab provides you with an IAM role ARN that connects to your endpoint service. You can then add this ARN to the allowlist on your side to restrict connections to your endpoint service.
1. [Create the Endpoint service](https://docs.aws.amazon.com/vpc/latest/privatelink/create-endpoint-service.html) through which your internal service is available to GitLab Dedicated. Provide the associated `Service Endpoint Name` on the [support ticket](#configuration-changes).
1. In your [support ticket](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=4414917877650), GitLab provides you with an IAM role ARN that connects to your endpoint service. You can then add this ARN to the allowlist on your side to restrict connections to your endpoint service.
1. [Create the Endpoint service](https://docs.aws.amazon.com/vpc/latest/privatelink/create-endpoint-service.html) through which your internal service is available to GitLab Dedicated. Provide the associated `Service Endpoint Name` on the [support ticket](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=4414917877650).
1. When creating the Endpoint service, you must provide GitLab with a [verified Private DNS Name](https://docs.aws.amazon.com/vpc/latest/privatelink/manage-dns-names.html#verify-domain-ownership) for your service. Optionally, if you would like GitLab Dedicated to reach your service via other aliases, you have the ability to specify a list of Private Hosted Zone (PHZ) entries. With this option, GitLab sets up a Private Hosted Zone with DNS names aliased to the verified Private DNS name. To enable this functionality, you must provide GitLab a list of PHZ entries on your support ticket. After the PHZ is created in the tenant environment, DNS resolution of any of the provided records correctly resolves to the PrivateLink endpoint.
1. GitLab then configures the tenant instance to create the necessary Endpoint Interfaces based on the service names you provided. Any outbound calls made from the tenant GitLab instance are directed through the PrivateLink into your VPC.
@ -190,7 +190,7 @@ To enable an Outbound Private Link:
In some cases, the GitLab Dedicated instance can't reach an internal service you own because it exposes a certificate that can't be validated using a public Certification Authority (CA). In these cases, custom certificates are required.
To request that GitLab add custom certificates when communicating with your services over PrivateLink, attach the custom public certificate files to your [support ticket](#configuration-changes).
To request that GitLab add custom certificates when communicating with your services over PrivateLink, attach the custom public certificate files to your [support ticket](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=4414917877650).
#### Maximum number of reverse PrivateLink connections
@ -200,7 +200,7 @@ GitLab Dedicated limits the number of reverse PrivateLink connections to 10.
GitLab Dedicated allows you to control which IP addresses can access your instance through an IP allowlist.
Specify a comma separated list of IP addresses that can access your GitLab Dedicated instance in your [support ticket](#configuration-changes). After the configuration has been applied, when an IP not on the allowlist tries to access your instance, the connection is refused.
Specify a comma separated list of IP addresses that can access your GitLab Dedicated instance in your [support ticket](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=4414917877650). After the configuration has been applied, when an IP not on the allowlist tries to access your instance, the connection is refused.
### SAML
@ -210,7 +210,7 @@ Prerequisites:
To activate SAML for your GitLab Dedicated instance:
1. To make the necessary changes, include the desired [SAML configuration block](../../integration/saml.md#configure-saml-support-in-gitlab) for your GitLab application in your [support ticket](#configuration-changes). At a minimum, GitLab needs the following information to enable SAML for your instance:
1. To make the necessary changes, include the desired [SAML configuration block](../../integration/saml.md#configure-saml-support-in-gitlab) for your GitLab application in your [support ticket](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=4414917877650). At a minimum, GitLab needs the following information to enable SAML for your instance:
- Assertion consumer service URL
- Certificate fingerprint or certificate
- NameID format
@ -225,13 +225,13 @@ To activate SAML for your GitLab Dedicated instance:
If [SAML request signing](../../integration/saml.md#sign-saml-authentication-requests-optional) is desired, a certificate must be obtained. This certificate can be self-signed which has the advantage of not having to prove ownership of an arbitrary Common Name (CN) to a public Certificate Authority (CA)).
To enable SAML request signing, indicate on your SAML [support ticket](#configuration-changes) that you want request signing enabled. GitLab works with you on sending the Certificate Signing Request (CSR) for you to sign. Alternatively, the CSR can be signed with a public CA. After the certificate is signed, GitLab adds the certificate and its associated private key to the `security` section of the SAML configuration. Authentication requests from GitLab to your identity provider can then be signed.
To enable SAML request signing, indicate on your SAML [support ticket](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=4414917877650) that you want request signing enabled. GitLab works with you on sending the Certificate Signing Request (CSR) for you to sign. Alternatively, the CSR can be signed with a public CA. After the certificate is signed, GitLab adds the certificate and its associated private key to the `security` section of the SAML configuration. Authentication requests from GitLab to your identity provider can then be signed.
#### SAML groups
With SAML groups you can configure GitLab users based on SAML group membership.
To enable SAML groups, add the [required elements](../../integration/saml.md#configure-users-based-on-saml-group-membership) to the SAML configuration block you provide in your [support ticket](#configuration-changes).
To enable SAML groups, add the [required elements](../../integration/saml.md#configure-users-based-on-saml-group-membership) to the SAML configuration block you provide in your [support ticket](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=4414917877650).
#### Group sync
@ -239,7 +239,7 @@ With [group sync](../../user/group/saml_sso/group_sync.md), you can sync users a
To enable group sync:
1. Add the [required elements](../../user/group/saml_sso/group_sync.md#configure-saml-group-sync) to the SAML configuration block you provide in your [support ticket](#configuration-changes).
1. Add the [required elements](../../user/group/saml_sso/group_sync.md#configure-saml-group-sync) to the SAML configuration block you provide in your [support ticket](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=4414917877650).
1. Configure the [Group Links](../../user/group/saml_sso/group_sync.md#configure-saml-group-links).
### Access to application logs
@ -248,5 +248,5 @@ GitLab [application logs](../../administration/logs/index.md) are delivered to a
To gain read only access to this bucket:
1. Open a [support ticket](#configuration-changes) with the title "Customer Log Access". In the body of the ticket, include a list of IAM Principal ARNs (users or roles) that are fetching the logs from S3.
1. Open a [support ticket](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=4414917877650) with the title "Customer Log Access". In the body of the ticket, include a list of IAM Principal ARNs (users or roles) that are fetching the logs from S3.
1. GitLab then informs you of the name of the S3 bucket. Your nominated users/roles can then able to list and get all objects in the S3 bucket.

View File

@ -430,7 +430,12 @@ You can update project approval rules using the following endpoint:
PUT /projects/:id/approval_rules/:approval_rule_id
```
**Important:** Approvers and groups not in the `users`/`groups` parameters are **removed**
NOTE:
Approvers and groups (except hidden groups not in the `users` or `groups`
parameters) are **removed**. Hidden groups are private groups the user doesn't
have permission to view. Hidden groups are not removed by default unless the
`remove_hidden_groups` parameter is `true`. This ensures hidden groups are
not removed unintentionally when a user updates an approval rule.
Supported attributes:
@ -443,7 +448,7 @@ Supported attributes:
| `applies_to_all_protected_branches` | boolean | **{dotted-circle}** No | Whether the rule is applied to all protected branches. If set to `true`, the value of `protected_branch_ids` is ignored. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/335316) in GitLab 15.3. |
| `group_ids` | Array | **{dotted-circle}** No | The IDs of groups as approvers. |
| `protected_branch_ids` | Array | **{dotted-circle}** No | The IDs of protected branches to scope the rule by. To identify the ID, [use the API](protected_branches.md#list-protected-branches). |
| `remove_hidden_groups` | boolean | **{dotted-circle}** No | Whether hidden groups should be removed. |
| `remove_hidden_groups` | boolean | **{dotted-circle}** No | Whether hidden groups should be removed from approval rule. |
| `user_ids` | Array | **{dotted-circle}** No | The IDs of users as approvers. If you provide both `user_ids` and `usernames`, both lists of users are added. |
| `usernames` | string array | **{dotted-circle}** No | The usernames of approvers for this rule (same as `user_ids` but requires a list of usernames). If you provide both `user_ids` and `usernames`, both lists of users are added.|

View File

@ -68,8 +68,8 @@ The following guides provide a quick introduction and links to follow on more ad
- Guide on [understanding EXPLAIN plans](understanding_explain_plans.md).
- [Explaining the unexplainable series in `depesz`](https://www.depesz.com/tag/unexplainable/).
We also have licensed access to The Art of PostgreSQL. If you are interested in getting access, check out the
[issue (confidential)](https://gitlab.com/gitlab-org/database-team/team-tasks/-/issues/23).
We also have licensed access to The Art of PostgreSQL. If you are interested in getting access, GitLab team
members can check out the issue here: `https://gitlab.com/gitlab-org/database-team/team-tasks/-/issues/23`.
Finally, you can find various guides in the [Database guides](index.md) page that cover more specific
topics and use cases. The most frequently required during database reviewing are the following:

View File

@ -1363,7 +1363,7 @@ end
When doing so be sure to explicitly set the model's table name, so it's not
derived from the class name or namespace.
Be aware of the limitations [when using models in migrations](#using-models-in-migrations-discouraged).
Be aware of the limitations [when using models in migrations](#using-application-code-in-migrations-discouraged).
### Modifying existing data
@ -1423,13 +1423,25 @@ _namespaces_ that have a `project_id`.
The `path` column for these rows are renamed to their previous value followed
by an integer. For example: `users` would turn into `users0`
## Using models in migrations (discouraged)
## Using application code in migrations (discouraged)
The use of models in migrations is generally discouraged. As such models are
[contraindicated for batched background migrations](database/batched_background_migrations.md#isolation),
the model needs to be declared in the migration.
The use of application code (including models) in migrations is generally
discouraged. This is because the migrations stick around for a long time and
the application code it depends on may change and break the migration in
future. In the past some background migrations needed to use
application code in order to avoid copying hundreds of lines of code spread
across multiple files into the migration. In these rare cases it's critical to
ensure the migration has good tests so that anyone refactoring the code in
future will learn if they break the migration. Using application code is also
[discouraged for batched background migrations](database/batched_background_migrations.md#isolation)
, the model needs to be declared in the migration.
If using a model in the migrations, you should first
Usually you can avoid using application code (specifically models) in a
migration by defining a class that inherits from `MigrationRecord` (see
examples below).
If using are using a model (including defined in the migration), you should
first
[clear the column cache](https://api.rubyonrails.org/classes/ActiveRecord/ModelSchema/ClassMethods.html#method-i-reset_column_information)
using `reset_column_information`.

View File

@ -58,7 +58,9 @@ The best results from Code Suggestions are expected [for languages the Google Ve
- Swift
- TypeScript
Supported [code infrastructure interfaces](https://cloud.google.com/vertex-ai/docs/generative-ai/code/code-models-overview#supported_code_infrastructure_interfaces) include:
## Supported code infrastructure interfaces
Code Suggestions includes [Google Vertex AI Codey APIs](https://cloud.google.com/vertex-ai/docs/generative-ai/code/code-models-overview#supported_code_infrastructure_interfaces) support for the following infrastructure as code interfaces:
- Google Cloud CLI
- Kubernetes Resource Model (KRM)

View File

@ -8406,6 +8406,9 @@ msgstr ""
msgid "BroadcastMessages|Add broadcast message"
msgstr ""
msgid "BroadcastMessages|Add new message"
msgstr ""
msgid "BroadcastMessages|Allow users to dismiss the broadcast message"
msgstr ""
@ -8418,9 +8421,18 @@ msgstr ""
msgid "BroadcastMessages|Dark"
msgstr ""
msgid "BroadcastMessages|Delete broadcast message"
msgstr ""
msgid "BroadcastMessages|Delete message"
msgstr ""
msgid "BroadcastMessages|Dismissable"
msgstr ""
msgid "BroadcastMessages|Do you really want to delete this broadcast message?"
msgstr ""
msgid "BroadcastMessages|Ends at"
msgstr ""
@ -8451,6 +8463,12 @@ msgstr ""
msgid "BroadcastMessages|Message"
msgstr ""
msgid "BroadcastMessages|Messages"
msgstr ""
msgid "BroadcastMessages|No broadcast messages defined yet."
msgstr ""
msgid "BroadcastMessages|Notification"
msgstr ""

View File

@ -3,7 +3,7 @@
source 'https://rubygems.org'
gem 'gitlab-qa', '~> 12', '>= 12.2.0', require: 'gitlab/qa'
gem 'gitlab_quality-test_tooling', '~> 0.8.3', require: false
gem 'gitlab_quality-test_tooling', '~> 0.9.3', require: false
gem 'gitlab-utils', path: '../gems/gitlab-utils'
gem 'activesupport', '~> 7.0.5.1' # This should stay in sync with the root's Gemfile
gem 'allure-rspec', '~> 2.20.0'

View File

@ -128,7 +128,7 @@ GEM
rainbow (>= 3, < 4)
table_print (= 1.5.7)
zeitwerk (>= 2, < 3)
gitlab_quality-test_tooling (0.8.3)
gitlab_quality-test_tooling (0.9.3)
activesupport (>= 6.1, < 7.1)
gitlab (~> 4.19)
http (~> 5.0)
@ -350,7 +350,7 @@ DEPENDENCIES
fog-google (~> 1.19)
gitlab-qa (~> 12, >= 12.2.0)
gitlab-utils!
gitlab_quality-test_tooling (~> 0.8.3)
gitlab_quality-test_tooling (~> 0.9.3)
influxdb-client (~> 2.9)
knapsack (~> 4.0)
nokogiri (~> 1.15, >= 1.15.3)

View File

@ -12,6 +12,12 @@ RSpec.describe 'Admin Broadcast Messages', :js, feature_category: :onboarding do
# create
visit admin_broadcast_messages_path
click_button('Add new message')
page.within(preview_container) do
expect(page).to have_content('Your message here')
end
fill_in 'Message', with: 'test message'
wait_for_requests
@ -24,10 +30,6 @@ RSpec.describe 'Admin Broadcast Messages', :js, feature_category: :onboarding do
wait_for_requests
page.within(preview_container) do
expect(page).to have_content('Your message here')
end
page.within(first_message_container) do
expect(page).to have_content('test message')
end
@ -53,10 +55,6 @@ RSpec.describe 'Admin Broadcast Messages', :js, feature_category: :onboarding do
wait_for_requests
page.within(preview_container) do
expect(page).to have_content('Your message here')
end
page.within(first_message_container) do
expect(page).to have_content('changed test message')
end

View File

@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Broadcast Messages', feature_category: :onboarding do
include Spec::Support::Helpers::ModalHelpers
let_it_be(:user) { create(:user) }
let(:path) { explore_projects_path }
@ -127,6 +129,8 @@ RSpec.describe 'Broadcast Messages', feature_category: :onboarding do
find("[data-testid='delete-message-#{message.id}']").click
end
accept_gl_confirm(button_text: 'Delete message')
visit path
expect_no_broadcast_message

View File

@ -1,3 +1,4 @@
import { GlModal } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MessagesTable from '~/admin/broadcast_messages/components/messages_table.vue';
import { MOCK_MESSAGES } from '../mock_data';
@ -8,6 +9,7 @@ describe('MessagesTable', () => {
const findRows = () => wrapper.findAll('[data-testid="message-row"]');
const findTargetRoles = () => wrapper.find('[data-testid="target-roles-th"]');
const findDeleteButton = (id) => wrapper.find(`[data-testid="delete-message-${id}"]`);
const findModal = () => wrapper.findComponent(GlModal);
function createComponent(props = {}) {
wrapper = mount(MessagesTable, {
@ -34,6 +36,8 @@ describe('MessagesTable', () => {
const { id } = MOCK_MESSAGES[0];
createComponent();
findDeleteButton(id).element.click();
findModal().vm.$emit('primary');
expect(wrapper.emitted('delete-message')).toHaveLength(1);
expect(wrapper.emitted('delete-message')[0]).toEqual([id]);
});

View File

@ -78,7 +78,6 @@ const createComponent = async (mockData = {}, mountFn = shallowMount, mockRoute
createMergeRequestIn = userPermissionsMock.createMergeRequestIn,
isBinary,
inject = {},
highlightJs = true,
} = mockData;
const blobInfo = {
@ -151,7 +150,6 @@ const createComponent = async (mockData = {}, mountFn = shallowMount, mockRoute
originalBranch: 'default-ref',
...inject,
glFeatures: {
highlightJs,
highlightJsWorker: false,
},
},
@ -223,16 +221,6 @@ describe('Blob content viewer component', () => {
describe('legacy viewers', () => {
const fileType = 'text';
const highlightJs = false;
it('loads a legacy viewer when a the fileType is text and the highlightJs feature is turned off', async () => {
await createComponent({
blob: { ...simpleViewerMock, fileType, highlightJs },
});
expect(mockAxios.history.get).toHaveLength(1);
expect(mockAxios.history.get[0].url).toBe(legacyViewerUrl);
});
it('loads a legacy viewer when the source viewer emits an error', async () => {
loadViewer.mockReturnValueOnce(SourceViewer);
@ -261,19 +249,19 @@ describe('Blob content viewer component', () => {
it('loads the LineHighlighter', async () => {
mockAxios.onGet(legacyViewerUrl).replyOnce(HTTP_STATUS_OK, 'test');
await createComponent({ blob: { ...simpleViewerMock, fileType, highlightJs } });
await createComponent({ blob: { ...simpleViewerMock, fileType } });
expect(LineHighlighter).toHaveBeenCalled();
});
it('does not load the LineHighlighter for RichViewers', async () => {
mockAxios.onGet(legacyViewerUrl).replyOnce(HTTP_STATUS_OK, 'test');
await createComponent({ blob: { ...richViewerMock, fileType, highlightJs } });
await createComponent({ blob: { ...richViewerMock, fileType } });
expect(LineHighlighter).not.toHaveBeenCalled();
});
it('scrolls to the hash', async () => {
mockAxios.onGet(legacyViewerUrl).replyOnce(HTTP_STATUS_OK, 'test');
await createComponent({ blob: { ...simpleViewerMock, fileType, highlightJs } });
await createComponent({ blob: { ...simpleViewerMock, fileType } });
expect(handleLocationHash).toHaveBeenCalled();
});
});
@ -516,20 +504,13 @@ describe('Blob content viewer component', () => {
});
describe('blob info query', () => {
it.each`
highlightJs | shouldFetchRawText
${true} | ${true}
${false} | ${false}
`(
'calls blob info query with shouldFetchRawText: $shouldFetchRawText when highlightJs (feature flag): $highlightJs',
async ({ highlightJs, shouldFetchRawText }) => {
await createComponent({ highlightJs });
it('calls blob info query with shouldFetchRawText: true', async () => {
await createComponent();
expect(blobInfoMockResolver).toHaveBeenCalledWith(
expect.objectContaining({ shouldFetchRawText }),
);
},
);
expect(blobInfoMockResolver).toHaveBeenCalledWith(
expect.objectContaining({ shouldFetchRawText: true }),
);
});
it('is called with originalBranch value if the prop has a value', async () => {
await createComponent({ inject: { originalBranch: 'some-branch' } });

View File

@ -41,9 +41,23 @@ describe('MRWidgetHowToMerge', () => {
expect(findTipLink().exists()).toBe(false);
});
it('should render different instructions based on if the user can merge', () => {
mountComponent({ props: { canMerge: true } });
expect(findInstructionsFields().at(1).text()).toContain('git push origin');
it('should render instructions to push', () => {
mountComponent({ props: { sourceBranch: 'branch-of-user' } });
expect(findInstructionsFields().at(1).text()).toContain("git push origin 'branch-of-user'");
});
it('should render instructions to push to fork', () => {
mountComponent({
props: {
sourceProjectDefaultUrl: 'git@gitlab.com:contributor/Underscore.git',
sourceProjectPath: 'Underscore',
sourceBranch: 'branch-of-user',
isFork: true,
},
});
expect(findInstructionsFields().at(1).text()).toContain(
'git push "git@gitlab.com:contributor/Underscore.git" \'Underscore-branch-of-user:branch-of-user\'',
);
});
it('escapes the source branch name shell-secure', () => {