Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-10-05 06:10:52 +00:00
parent fdb5a6d73c
commit 9fae295466
31 changed files with 308 additions and 233 deletions

View File

@ -1 +1 @@
3e0b54959f433192b6147792427fa4521e5724b5
82988a601f0ae35d7c260bfe01d3304e642429db

View File

@ -7,6 +7,7 @@ import Tracking from '~/tracking';
import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import { n__, sprintf } from '~/locale';
import { memberName, triggerExternalAlert } from 'ee_else_ce/invite_members/utils/member_utils';
import { captureException } from '~/ci/runner/sentry_utils';
import {
USERS_FILTER_ALL,
MEMBER_MODAL_LABELS,
@ -262,8 +263,9 @@ export default {
} else {
this.onInviteSuccess();
}
} catch (e) {
this.showInvalidFeedbackMessage(e);
} catch (error) {
captureException({ error, component: this.$options.name });
this.showInvalidFeedbackMessage(error);
} finally {
this.isLoading = false;
}

View File

@ -87,7 +87,7 @@ export default {
<gl-button
category="primary"
variant="danger"
data-qa-selector="delete_button"
data-testid="delete-button"
@click="onButtonClick"
>{{ $options.i18n.deleteProject }}</gl-button
>

View File

@ -51,7 +51,7 @@ export default {
:disabled="!hasSelectedNamespace"
:phrase="confirmationPhrase"
:button-text="confirmButtonText"
button-qa-selector="transfer_project_button"
button-testid="transfer-project-button"
@confirm="$emit('confirm')"
/>
</div>

View File

@ -36,4 +36,3 @@ export const SERVICE_PING_SECURITY_CONFIGURATION_THREAT_MANAGEMENT_VISIT =
'users_visiting_security_configuration_threat_management';
export const SERVICE_PING_PIPELINE_SECURITY_VISIT = 'users_visiting_pipeline_security';
export const USER_CONTEXT_SCHEMA = 'iglu:com.gitlab/user_context/jsonschema/1-0-0';

View File

@ -1,12 +1,10 @@
import API from '~/api';
import getStandardContext from './get_standard_context';
import Tracking from './tracking';
import {
GITLAB_INTERNAL_EVENT_CATEGORY,
LOAD_INTERNAL_EVENTS_SELECTOR,
SERVICE_PING_SCHEMA,
USER_CONTEXT_SCHEMA,
} from './constants';
import { Tracker } from './tracker';
import { InternalEventHandler, createInternalEventPayload } from './utils';
@ -91,18 +89,10 @@ const InternalEvents = {
* Initialize browser sdk for product analytics
*/
initBrowserSDK() {
const standardContext = getStandardContext();
if (window.glClient) {
window.glClient.setDocumentTitle('GitLab');
window.glClient.page({
title: 'GitLab',
context: [
{
schema: USER_CONTEXT_SCHEMA,
data: standardContext?.data || {},
},
],
});
}
},

View File

@ -177,7 +177,6 @@ module IssuablesHelper
markdownPreviewPath: preview_markdown_path(parent, target_type: issuable.model_name, target_id: issuable.iid),
markdownDocsPath: help_page_path('user/markdown'),
lockVersion: issuable.lock_version,
state: issuable.state,
issuableTemplateNamesPath: template_names_path(parent, issuable),
initialTitleHtml: markdown_field(issuable, :title),
initialTitleText: issuable.title,
@ -358,7 +357,6 @@ module IssuablesHelper
issuableId: issuable.id,
issueType: issuable.issue_type,
isHidden: issue_hidden?(issuable),
sentryIssueIdentifier: SentryIssue.find_by(issue: issuable)&.sentry_issue_identifier, # rubocop:disable CodeReuse/ActiveRecord
zoomMeetingUrl: ZoomMeeting.canonical_meeting_url(issuable),
**incident_only_initial_data(issuable),
**issue_header_data(issuable),

View File

@ -123,7 +123,7 @@ module Emails
@target_url = profile_personal_access_tokens_url
@source = source
mail_with_locale(to: @user.notification_email_or_default, subject: subject(_("A personal access token has been revoked")))
email_with_layout(to: @user.notification_email_or_default, subject: subject(_("Your personal access token has been revoked")))
end
def ssh_key_expired_email(user, fingerprints)

View File

@ -2,7 +2,7 @@
- project = local_assigns.fetch(:project)
= render Pajamas::CardComponent.new(card_options: { class: 'gl-new-card', data: { qa_selector: 'export_project_content' } }, header_options: { class: 'gl-new-card-header' }, body_options: { class: 'gl-new-card-body gl-px-5 gl-py-4' }) do |c|
= render Pajamas::CardComponent.new(card_options: { class: 'gl-new-card', data: { testid: 'export-project-content' } }, header_options: { class: 'gl-new-card-header' }, body_options: { class: 'gl-new-card-body gl-px-5 gl-py-4' }) do |c|
- c.with_header do
.gl-new-card-title-wrapper
%h4.gl-new-card-title= _('Export project')
@ -27,10 +27,10 @@
- if project.export_status == :finished
= render Pajamas::ButtonComponent.new(href: download_export_project_path(project),
method: :get,
button_options: { ref: 'nofollow', download: '', data: { qa_selector: 'download_export_link' } }) do
button_options: { ref: 'nofollow', download: '', data: { testid: 'download-export-link' } }) do
= _('Download export')
= render Pajamas::ButtonComponent.new(href: generate_new_export_project_path(project), method: :post) do
= _('Generate new export')
- else
= render Pajamas::ButtonComponent.new(href: export_project_path(project), method: :post, button_options: { data: { qa_selector: 'export_project_link' } }) do
= render Pajamas::ButtonComponent.new(href: export_project_path(project), method: :post, button_options: { data: { testid: 'export-project-link' } }) do
= _('Export project')

View File

@ -3,7 +3,7 @@
- hidden_input_id = "new_namespace_id"
- initial_data = { button_text: s_('ProjectSettings|Transfer project'), confirm_danger_message: transfer_project_message(@project), phrase: @project.name, target_form_id: form_id, target_hidden_input_id: hidden_input_id, project_id: @project.id }
= render Pajamas::CardComponent.new(card_options: { class: 'gl-new-card', data: { qa_selector: 'transfer_project_content' } }, header_options: { class: 'gl-new-card-header gl-flex-direction-column' }, body_options: { class: 'gl-new-card-body gl-px-5 gl-py-4' }) do |c|
= render Pajamas::CardComponent.new(card_options: { class: 'gl-new-card', data: { testid: 'transfer-project-content' } }, header_options: { class: 'gl-new-card-header gl-flex-direction-column' }, body_options: { class: 'gl-new-card-body gl-px-5 gl-py-4' }) do |c|
- c.with_header do
.gl-new-card-title-wrapper
%h4.gl-new-card-title.warning-title= _('Transfer project')

View File

@ -18,7 +18,7 @@
%p.gl-text-secondary= _('Update your project name, topics, description, and avatar.')
.settings-content= render 'projects/settings/general'
%section.settings.sharing-permissions.no-animate#js-shared-permissions{ class: ('expanded' if expanded), data: { qa_selector: 'visibility_features_permissions_content' } }
%section.settings.sharing-permissions.no-animate#js-shared-permissions{ class: ('expanded' if expanded), data: { testid: 'visibility-features-permissions-content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Visibility, project features, permissions')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
@ -38,7 +38,7 @@
- c.with_body do
= _('On the left sidebar, select %{merge_requests_link} to view them.').html_safe % { merge_requests_link: link_to('Settings > Merge requests', project_settings_merge_requests_path(@project)).html_safe }
%section.settings.no-animate{ class: ('expanded' if expanded), data: { qa_selector: 'badges_settings_content' } }
%section.settings.no-animate{ class: ('expanded' if expanded), data: { testid: 'badges-settings-content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= s_('ProjectSettings|Badges')
@ -56,7 +56,7 @@
= render 'projects/service_desk_settings'
%section.settings.advanced-settings.no-animate#js-project-advanced-settings{ class: ('expanded' if expanded), data: { qa_selector: 'advanced_settings_content' } }
%section.settings.advanced-settings.no-animate#js-project-advanced-settings{ class: ('expanded' if expanded), data: { testid: 'advanced-settings-content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Advanced')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
@ -107,8 +107,8 @@
.input-group-prepend
.input-group-text
#{Gitlab::Utils.append_path(root_url, @project.namespace.full_path)}/
= f.text_field :path, class: 'form-control gl-form-input-xl', data: { qa_selector: 'project_path_field' }
= f.submit _('Change path'), class: "btn-danger", data: { qa_selector: 'change_path_button' }, pajamas_button: true
= f.text_field :path, class: 'form-control gl-form-input-xl', data: { testid: 'project-path-field' }
= f.submit _('Change path'), class: "btn-danger", data: { testid: 'change-path-button' }, pajamas_button: true
= render 'transfer', project: @project

View File

@ -13,10 +13,10 @@
- if @project.archived?
- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/project/settings/index', anchor: 'unarchive-a-project') }
%p= _("Unarchiving the project restores its members' ability to make commits, and create issues, comments, and other entities. %{strong_start}After you unarchive the project, it displays in the search and on the dashboard.%{strong_end} %{link_start}Learn more.%{link_end}").html_safe % { strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe, link_start: link_start, link_end: '</a>'.html_safe }
= render Pajamas::ButtonComponent.new(method: :post, href: unarchive_project_path(@project), variant: :confirm, button_options: { aria: { label: _('Unarchive project') }, data: { confirm: _("Are you sure that you want to unarchive this project?"), qa_selector: 'unarchive_project_link' } }) do
= render Pajamas::ButtonComponent.new(method: :post, href: unarchive_project_path(@project), variant: :confirm, button_options: { aria: { label: _('Unarchive project') }, data: { confirm: _("Are you sure that you want to unarchive this project?"), testid: 'unarchive-project-link' } }) do
= _('Unarchive project')
- else
- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/project/settings/index', anchor: 'archive-a-project') }
%p= _("Archiving the project makes it entirely read-only. It is hidden from the dashboard and doesn't display in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}").html_safe % { strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe, link_start: link_start, link_end: '</a>'.html_safe }
= render Pajamas::ButtonComponent.new(method: :post, href: archive_project_path(@project), variant: :confirm, button_options: { aria: { label: _('Archive project') }, data: { confirm: _("Are you sure that you want to archive this project?"), qa_selector: 'archive_project_link', 'confirm-btn-variant': 'confirm' } }) do
= render Pajamas::ButtonComponent.new(method: :post, href: archive_project_path(@project), variant: :confirm, button_options: { aria: { label: _('Archive project') }, data: { confirm: _("Are you sure that you want to archive this project?"), testid: 'archive-project-link', 'confirm-btn-variant': 'confirm' } }) do
= _('Archive project')

View File

@ -7,7 +7,7 @@
.form-group.col-md-5
= f.label :name, class: 'label-bold', for: 'project_name_edit' do
= _('Project name')
= f.text_field :name, class: 'form-control gl-form-input', id: "project_name_edit", data: { qa_selector: 'project_name_field' }
= f.text_field :name, class: 'form-control gl-form-input', id: "project_name_edit", data: { testid: 'project-name-field' }
.form-group.col-md-7
= f.label :id, class: 'label-bold' do
@ -37,4 +37,4 @@
%hr
= link_button_to _('Remove avatar'), project_avatar_path(@project), aria: { label: _('Remove avatar') }, data: { confirm: _('Avatar will be removed. Are you sure?'), 'confirm-btn-variant': 'danger' }, method: :delete, variant: :danger, category: :secondary
= f.submit _('Save changes'), pajamas_button: true, class: "gl-mt-6", data: { qa_selector: 'save_naming_topics_avatar_button' }
= f.submit _('Save changes'), pajamas_button: true, class: "gl-mt-6", data: { testid: 'save-naming-topics-avatar-button' }

View File

@ -2,7 +2,7 @@
- page_title _('Merge requests')
- @force_desktop_expanded_sidebar = true
%section.rspec-merge-request-settings.settings.merge-requests-feature.no-animate#js-merge-request-settings.expanded{ class: [('hidden' if @project.project_feature.send(:merge_requests_access_level) == 0)], data: { qa_selector: 'merge_request_settings_content' } }
%section.rspec-merge-request-settings.settings.merge-requests-feature.no-animate#js-merge-request-settings.expanded{ class: [('hidden' if @project.project_feature.send(:merge_requests_access_level) == 0)], data: { testid: 'merge-request-settings-content' } }
.settings-header
%h4= _('Merge requests')
= render_if_exists 'projects/settings/merge_requests/merge_request_settings_description_text'

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
class SyncForeignKeyForCiSourcesPipelinesPipelineIdBigint < Gitlab::Database::Migration[2.1]
TABLE_NAME = :ci_sources_pipelines
COLUMN_NAME = :pipeline_id_convert_to_bigint
FK_NAME = :fk_c1b5dc6b6f
def up
validate_foreign_key TABLE_NAME, COLUMN_NAME, name: FK_NAME
end
def down
# Can be safely a no-op if we don't roll back the inconsistent data.
end
end

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
class SyncForeignKeyForCiSourcesPipelinesSourcePipelineIdBigint < Gitlab::Database::Migration[2.1]
TABLE_NAME = :ci_sources_pipelines
COLUMN_NAME = :source_pipeline_id_convert_to_bigint
FK_NAME = :fk_1df371767f
def up
validate_foreign_key TABLE_NAME, COLUMN_NAME, name: FK_NAME
end
def down
# Can be safely a no-op if we don't roll back the inconsistent data.
end
end

View File

@ -0,0 +1 @@
7793aafff32e777ad91843f6d5eb8f365b2d8bf6ea1d98f83096beda4831c32a

View File

@ -0,0 +1 @@
212db29694b69887d300c66446cf6dd167e724df9004dc5a8a571bd9bc3bfbaf

View File

@ -36709,7 +36709,7 @@ ALTER TABLE ONLY vulnerabilities
ADD CONSTRAINT fk_1d37cddf91 FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE SET NULL;
ALTER TABLE ONLY ci_sources_pipelines
ADD CONSTRAINT fk_1df371767f FOREIGN KEY (source_pipeline_id_convert_to_bigint) REFERENCES ci_pipelines(id) ON DELETE CASCADE NOT VALID;
ADD CONSTRAINT fk_1df371767f FOREIGN KEY (source_pipeline_id_convert_to_bigint) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
ALTER TABLE ONLY boards
ADD CONSTRAINT fk_1e9a074a35 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@ -37402,7 +37402,7 @@ ALTER TABLE ONLY packages_packages
ADD CONSTRAINT fk_c188f0dba4 FOREIGN KEY (creator_id) REFERENCES users(id) ON DELETE SET NULL;
ALTER TABLE ONLY ci_sources_pipelines
ADD CONSTRAINT fk_c1b5dc6b6f FOREIGN KEY (pipeline_id_convert_to_bigint) REFERENCES ci_pipelines(id) ON DELETE CASCADE NOT VALID;
ADD CONSTRAINT fk_c1b5dc6b6f FOREIGN KEY (pipeline_id_convert_to_bigint) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
ALTER TABLE ONLY sbom_occurrences
ADD CONSTRAINT fk_c2a5562923 FOREIGN KEY (source_id) REFERENCES sbom_sources(id) ON DELETE CASCADE;

View File

@ -13,14 +13,14 @@ This documentation will be kept even if we decide not to implement this so that
# Cells: Personal Namespaces
Personal Namespaces do not easily fit with our overall architecture in Cells because the Cells architecture depends on all data belonging to a single Organization.
Personal Namespaces do not easily fit with our overall architecture in Cells, because the Cells architecture depends on all data belonging to a single Organization.
When Users are allowed to work across multiple Organizations there is no natural fit for picking a single Organization to store personal Namespaces and their Projects.
One important engineering constraint in Cells will be that data belonging to some Organization should not be linked to data belonging to another Organization.
And specifically that functionality in GitLab can be scoped to a single Organization at a time.
One important engineering constraint in Cells will be that data belonging to one Organization should not be linked to data belonging to another Organization.
Specifically, functionality in GitLab should be scoped to a single Organization at a time.
This presents a challenge for personal Namespaces as forking is one of the important workloads for personal Namespaces.
Functionality related to forking and the UI that presents forked MRs to users will often require data from both the downstream and upstream Projects at the same time.
Implementing such functionality would be very difficult if that data belonged in different Organizations stored on different
Implementing such functionality would be very difficult if that data belonged to different Organizations stored on different
Cells.
This is especially the case with the merge request, as it is one of the most complicated and performance critical features in GitLab.
@ -46,26 +46,98 @@ As described above, personal Namespaces serve two purposes today:
1. A place for users to store forks when they want to contribute to a Project where they don't have permission to push a branch.
In this proposal we will only focus on (1) and assume that (2) will be replaced by suitable workflows described in [Cells: Contributions: Forks](../impacted_features/contributions-forks.md).
Since we plan to move away from using personal Namespaces as a home for storing forks, we can assume that the main remaining use case does not need to support cross-Organization linking.
In this case the easiest thing to do is to keep all personal Namespaces in the default Organization.
Depending on the amount of workloads happening in personal Namespaces we may be required in the future to migrate them to different Cells.
This may necessitate that they all get moved to some Organization created just for the user.
### 3.1. One personal Namespace that can move between Organizations
For existing Users personal Namespaces will exist within the default Organization in the short term.
This implies that all Users will, at first, have an association to the default Organization via their personal Namespace.
When a new Organization is created, new Users can be created in that Organization as well.
A new User's personal Namespace will be associated with that new Organization, rather than the default.
Also, Users can become members of Organizations other than the default Organization.
In this case, they will have to switch to the default Organization to access their personal Namespace until we have defined a way for them to move their personal Namespace into a different Home Organization.
Doing so may necessitate that personal Namespaces are converted to Groups before being moved.
When an Organization is deleted, we will need to decide what should happen with the personal Namespaces associated with it.
If we go this route, there may be breakage similar to what will happen to when we move Groups or Projects into their own Organization, though the full impact may need further investigation.
This decision, however, means that existing personal Namespaces that were used as forks to contribute to some upstream Project will become disconnected from the upstream as soon as the upstream moves into an Organization.
On GitLab.com 10% of all projects in personal Namespaces are forks.
This may be a slightly disruptive workflow but as long as the forks are mainly just storing branches used in merge requests then it may be reasonable to ask the affected users to recreate the fork in the context of the Organization.
For existing Users, we suggest to keep their existing personal Namespaces in the default Organization.
New Users joining an Organization other than the default Organization will also have their personal Namespace hosted on the default Organization. Having all personal Namespaces in the default Organization means we don't need to worry about deletion of the parent organization and the impact of that on personal Namespaces, which would be the case if they existed in other organizations.
This implies that all Users will have an association to the default Organization via their personal Namespace, requiring them to switch to the default Organization to access their personal Namespace.
We will further explore the idea of a `contribution space` to give Users a place to store forks when they want to contribute to a Project where they don't have permission to push a branch.
That discussion will be handled as part of the larger discussion of the [Cells impact on forks](../impacted_features/contributions-forks.md).
Pros:
- Easy access to personal Namespace via a User's Home Organization. We expect most Users to work in only a single Organization.
- Contribution graph would remain intact for Users that only work in one Organization, because their personal and organizational activity would be aggregated as part of the same Organization.
Cons:
- A transfer mechanism to move personal Namespaces between Organizations would need to be built, which is extremely complex. This would be in violation of the current Cells architecture, because Organizations can be located on different Cells. To make this possible, we would need to break Organization isolation.
- High risk that transfer between Organizations would lead to breaking connections and data loss.
- [Converting personal Namespaces to Groups](../../../../tutorials/convert_personal_namespace_to_group/index.md) before transfer is not a straightforward process.
### 3.2. One personal Namespace that remains in the default Organization
For existing Users personal Namespaces will exist within the default Organization in the short term.
This implies that all Users will, at first, have an association to the default Organization via their personal Namespace.
New Users joining GitLab as part of an Organization other than the default Organization would also receive a personal Namespace in the default Organization.
Organization other than the default Organization would not contain personal Namespaces.
Pros:
- No transfer mechanism necessary.
Cons:
- Users that are part of multiple Organizations need to remember that their personal content is stored in the default Organization. To access it, they would have to switch back to the default Organization.
- New Users might not understand why they are part of the default Organization.
- Some impact on the User Profile page. No personal Projects would be shown in Organizations other than the default Organization. This would result in a lot of whitespace on the page. The `Personal projects` list would need to be reworked as well.
### 3.3. One personal Namespace in each Organization
For existing Users personal Namespaces will exist within the default Organization in the short term.
As new Organizations are created, Users receive additional personal Namespaces for each Organization they interact with.
For instance, when a User views a Group or Project in an Organization, a personal Namespace is created.
This is necessary to ensure that community contributors will be able to continue contributing to Organizations without becoming a member.
Pros:
- Content of personal Projects is owned by the Organization. Low risk for enterprises to leak content outside of their organizational boundaries.
- No transfer mechanism necessary.
- No changes to the User Profile page are necessary.
- Users can keep personal Projects in each Organization they work in.
- No contribution space for [forking](../impacted_features/contributions-forks.md) necessary.
- No need to make the default Organization function differently than other Organizations.
Cons:
- Users have to remember which personal content they store in each Organization.
- Personal content would be owned by the Organization. However, this would be similar to how self-managed operates today and might be desired by enterprises.
### 3.4. Discontinue personal Namespaces
All existing personal Namespaces are converted into Groups.
The Group path is identical to the current username.
Upon Organization release, these Groups would be part of the default Organization.
We disconnect Users from the requirement of having personal Namespaces, making the User a truly global entity.
Pros:
- Users would receive the ability to organize personal Projects into Groups, which is a highly requested feature.
- No need to create personal Namespaces upon User creation.
- No path changes necessary for existing personal Projects.
Cons:
- A concept of personal Groups would need to be established.
- It is unclear how @-mentions would work. Currently it is possible to tag individual Users and Groups. Following the existing logic all group members belonging to a personal Group would be tagged.
- Significant impact on the User Profile page. Personal Projects would be disconnected from the User Profile page and possibly replaced by new functionality to highlight specific Projects selected by the User (via starring or pinning).
- It is unclear whether Groups could be migrated between Organizations using the same mechanism as needed to migrate top-level Groups. We expect this functionality to be highly limited at least in the mid-term. Similar transfer limitations as described in [section 3.1.](#31-one-personal-namespace-that-can-move-between-organizations) are expected.
## 4. Evaluation
## 4.1. Pros
## 4.2. Cons
The most straightforward solution requiring the least engineering effort is to create [one personal Namespace in each Organization](#33-one-personal-namespace-in-each-organization).
We recognize that this solution is not ideal for users working across multiple Organizations, but find this acceptable due to our expectation that most users will mainly work in one Organization.
At a later point, this concept will be reviewed and possibly replaced with a better solution.

View File

@ -167,6 +167,32 @@ separation of duties is:
- [A merge request committer is **not** allowed to approve a merge request they have added commits to](../../project/merge_requests/approvals/settings.md#prevent-approvals-by-users-who-add-commits).
- [The minimum number of approvals required to merge a merge request is **at least** two](../../project/merge_requests/approvals/rules.md).
### Export a report of merge request compliance violations on projects in a group
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/356791) in GitLab 16.4 [with a flag](../../../administration/feature_flags.md) named `compliance_violation_csv_export`. Disabled by default.
FLAG:
On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../../../administration/feature_flags.md) named
`compliance_violation_csv_export`. On GitLab.com, this feature is not available. The feature is not ready for production use.
Export a report of merge request compliance violations on merge requests belonging to projects in a group. Reports:
- Do not use filters on the violations report.
- Are truncated at 15 MB so the email attachment is not too large.
Prerequisites:
- You must be an administrator or have the Owner role for the group.
To export a report of merge request compliance violations for projects in a group:
1. On the left sidebar, select **Search or go to** and find your group.
1. On the left sidebar, select **Secure > Compliance center**.
1. On the page, select the **Violations** tab.
1. On the Violations tab, select the **Export full report as CSV** action in the top right corner
A report is compiled and delivered to your email inbox as an attachment.
### Chain of Custody report
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213364) in GitLab 13.3.
@ -234,11 +260,12 @@ Depending on your version of GitLab, the Chain of Custody report is either sent
Alternatively, use a direct link: `https://gitlab.com/groups/<group-name>/-/security/merge_commit_reports.csv?commit_sha={optional_commit_sha}`,
passing in an optional value to the `commit_sha` query parameter.
## Compliance frameworks report
## Compliance projects report
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/387910) in GitLab 15.10.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/387910) in GitLab 15.10.
> - [Renamed from **compliance frameworks report**](https://gitlab.com/gitlab-org/gitlab/-/issues/422963) in GitLab 16.5.
With compliance frameworks report, you can see the compliance frameworks that are applied to projects in a group. Each row of the report shows:
With compliance projects report, you can see the compliance frameworks that are applied to projects in a group. Each row of the report shows:
- Project name.
- Project path.
@ -246,17 +273,17 @@ With compliance frameworks report, you can see the compliance frameworks that ar
The default framework for the group has a **default** badge.
### View the compliance frameworks report for a group
### View the compliance projects report for a group
Prerequisites:
- You must be an administrator or have the Owner role for the group.
To view the compliance frameworks report:
To view the compliance projects report:
1. On the left sidebar, select **Search or go to** and find your group.
1. On the left sidebar, select **Secure > Compliance center**.
1. On the page, select the **Frameworks** tab.
1. On the page, select the **Projects** tab.
### Apply a compliance framework to projects in a group
@ -273,7 +300,7 @@ To apply a compliance framework to one project in a group:
1. On the left sidebar, select **Search or go to** and find your group.
1. On the left sidebar, select **Secure > Compliance center**.
1. On the page, select the **Frameworks** tab.
1. On the page, select the **Projects** tab.
1. Next to the project you want to add the compliance framework to, select **{plus}** **Add framework**.
1. Select an existing compliance framework or create a new one.
@ -281,7 +308,7 @@ To apply a compliance framework to multiple projects in a group:
1. On the left sidebar, select **Search or go to** and find your group.
1. On the left sidebar, select **Secure > Compliance center**.
1. On the page, select the **Frameworks** tab.
1. On the page, select the **Projects** tab.
1. Select multiple projects.
1. From the **Choose one bulk action** dropdown list, select **Apply framework to selected projects**.
1. Select framework to apply.
@ -302,44 +329,18 @@ To remove a compliance framework from one project in a group:
1. On the left sidebar, select **Search or go to** and find your group.
1. On the left sidebar, select **Secure > Compliance center**.
1. On the page, select the **Frameworks** tab.
1. On the page, select the **Projects** tab.
1. Next to the compliance framework to remove from the project, select **{close}** on the framework label.
To remove a compliance framework from multiple projects in a group:
1. On the left sidebar, select **Search or go to** and find your group.
1. On the left sidebar, select **Secure > Compliance center**.
1. On the page, select the **Frameworks** tab.
1. On the page, select the **Projects** tab.
1. Select multiple projects.
1. From the **Choose one bulk action** dropdown list, select **Remove framework from selected projects**.
1. Select **Remove**.
### Export a report of merge request compliance violations on projects in a group
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/356791) in GitLab 16.4 [with a flag](../../../administration/feature_flags.md) named `compliance_violation_csv_export`. Disabled by default.
FLAG:
On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../../../administration/feature_flags.md) named
`compliance_violation_csv_export`. On GitLab.com, this feature is not available. The feature is not ready for production use.
Export a report of merge request compliance violations on merge requests belonging to projects in a group. Reports:
- Do not use filters on the violations report.
- Are truncated at 15 MB so the email attachment is not too large.
Prerequisites:
- You must be an administrator or have the Owner role for the group.
To export a report of merge request compliance violations for projects in a group:
1. On the left sidebar, select **Search or go to** and find your group.
1. On the left sidebar, select **Secure > Compliance center**.
1. On the page, select the **Violations** tab.
1. On the Violations tab, select the **Export full report as CSV** action in the top right corner
A report is compiled and delivered to your email inbox as an attachment.
### Export a report of compliance frameworks on projects in a group
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/387912) in GitLab 16.0.
@ -357,12 +358,12 @@ To export a report of compliance frameworks on projects in a group:
1. On the left sidebar, select **Search or go to** and find your group.
1. On the left sidebar, select **Secure > Compliance center**.
1. On the page, select the **Frameworks** tab.
1. On the page, select the **Projects** tab.
1. On the Frameworks tab, select the **Export as CSV** action in the top right corner
A report is compiled and delivered to your email inbox as an attachment.
#### Filter the compliance frameworks report
#### Filter the compliance projects report
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/387911) in GitLab 15.11.
@ -370,7 +371,7 @@ To filter the list of compliance frameworks:
1. On the left sidebar, select **Search or go to** and find your group.
1. On the left sidebar, select **Secure > Compliance center**.
1. On the page, select the **Frameworks** tab.
1. On the page, select the **Projects** tab.
1. In the search field:
1. Select the attribute you want to filter by.
1. Select an operator.
@ -378,3 +379,30 @@ To filter the list of compliance frameworks:
1. Select **Search** (**{search}**).
Repeat this process to filter by multiple attributes.
## Compliance frameworks report
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/422973) in GitLab 16.5 [with a flag](../../../administration/feature_flags.md) named `compliance_framework_report_ui`. Disabled by default.
> - In GitLab 16.4 and earlier, **Compliance frameworks report** referred to what is now called **Compliance projects report**. The formally-named **Compliance frameworks report** was [renamed to **Compliance projects report**](https://gitlab.com/gitlab-org/gitlab/-/issues/422963) in GitLab 16.5.
FLAG:
On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../../../administration/feature_flags.md) named
`compliance_framework_report_ui`. On GitLab.com, this feature is not available. The feature is not ready for production use.
With compliance frameworks report, you can see all the compliance frameworks in a group. Each row of the report shows:
- Framework name.
The default framework for the group has a **default** badge.
### View the compliance frameworks report for a group
Prerequisites:
- You must be an administrator or have the Owner role for the group.
To view the compliance projects report:
1. On the left sidebar, select **Search or go to** and find your group.
1. On the left sidebar, select **Secure > Compliance center**.
1. On the page, select the **Frameworks** tab.

View File

@ -1838,9 +1838,6 @@ msgstr ""
msgid "A parent must be provided when bulk updating issuables"
msgstr ""
msgid "A personal access token has been revoked"
msgstr ""
msgid "A personal access token, named %{code_start}%{token_name}%{code_end}, has been revoked."
msgstr ""
@ -12125,15 +12122,15 @@ msgstr ""
msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
msgid "Compliance Center|Export frameworks as CSV. You will be emailed after the export is processed."
msgstr ""
msgid "Compliance Center|Export full report as CSV"
msgstr ""
msgid "Compliance Center|Export merge request violations as CSV. You will be emailed after the export is processed."
msgstr ""
msgid "Compliance Center|Export projects as CSV. You will be emailed after the export is processed."
msgstr ""
msgid "Compliance Center|Frameworks"
msgstr ""
@ -12326,6 +12323,9 @@ msgstr ""
msgid "ComplianceReport|Less than 2 approvers"
msgstr ""
msgid "ComplianceReport|No frameworks found"
msgstr ""
msgid "ComplianceReport|No projects found"
msgstr ""
@ -12353,6 +12353,9 @@ msgstr ""
msgid "ComplianceReport|Unable to load the compliance framework projects report. Refresh the page and try again."
msgstr ""
msgid "ComplianceReport|Unable to load the compliance framework report. Refresh the page and try again."
msgstr ""
msgid "ComplianceReport|Unable to load the compliance violations report. Refresh the page and try again."
msgstr ""
@ -20740,6 +20743,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
msgid "Frameworks"
msgstr ""
msgid "Frameworks can not be added to projects in personal namespaces. %{linkStart}What are personal namespaces?%{linkEnd}"
msgstr ""
@ -55145,6 +55151,9 @@ msgstr ""
msgid "Your password reset token has expired."
msgstr ""
msgid "Your personal access token has been revoked"
msgstr ""
msgid "Your personal access tokens have expired"
msgstr ""

View File

@ -10,31 +10,31 @@ module QA
include Component::NamespaceSelect
view 'app/assets/javascripts/projects/components/shared/delete_button.vue' do
element :delete_button
element 'delete-button'
end
view 'app/views/projects/edit.html.haml' do
element :project_path_field
element :change_path_button
element 'project-path-field'
element 'change-path-button'
end
view 'app/views/projects/settings/_archive.html.haml' do
element :archive_project_link
element :unarchive_project_link
element 'archive-project-link'
element 'unarchive-project-link'
end
view 'app/views/projects/_export.html.haml' do
element :export_project_link
element :download_export_link
element :export_project_content
element 'export-project-link'
element 'download-export-link'
element 'export-project-content'
end
view 'app/views/projects/_transfer.html.haml' do
element :transfer_project_content
element 'transfer-project-content'
end
view 'app/assets/javascripts/projects/settings/components/transfer_project_form.vue' do
element :transfer_project_button
element 'transfer-project-button'
end
def update_project_path_to(path)
@ -43,11 +43,11 @@ module QA
end
def fill_project_path(path)
fill_element :project_path_field, path
fill_element 'project-path-field', path
end
def click_change_path_button
click_element :change_path_button
click_element 'change-path-button'
end
def transfer_project!(project_name, namespace)
@ -61,36 +61,36 @@ module QA
wait_for_enabled_transfer_project_button
click_element :transfer_project_button
click_element 'transfer-project-button'
fill_confirmation_text(project_name)
confirm_transfer
end
def click_export_project_link
click_element :export_project_link
click_element 'export-project-link'
end
def click_download_export_link
click_element :download_export_link
click_element 'download-export-link'
end
def has_download_export_link?
has_element? :download_export_link
has_element? 'download-export-link'
end
def archive_project
click_element :archive_project_link
click_element 'archive-project-link'
click_confirmation_ok_button
end
def unarchive_project
click_element :unarchive_project_link
click_element 'unarchive-project-link'
click_confirmation_ok_button
end
def delete_project!(project_name)
click_element :delete_button
click_element 'delete-button'
fill_confirmation_path(project_name)
wait_for_delete_button_enabled
confirm_delete
@ -100,15 +100,15 @@ module QA
def scroll_to_transfer_project_content
retry_until(sleep_interval: 1, message: 'Waiting for transfer project content to display') do
has_element?(:transfer_project_content, wait: 3)
has_element?('transfer-project-content', wait: 3)
end
scroll_to_element :transfer_project_content
scroll_to_element 'transfer-project-content'
end
def wait_for_enabled_transfer_project_button
retry_until(sleep_interval: 1, message: 'Waiting for transfer project button to be enabled') do
has_element?(:transfer_project_button, disabled: false, wait: 3)
has_element?('transfer-project-button', disabled: false, wait: 3)
end
end
end

View File

@ -10,18 +10,18 @@ module QA
include Layout::Flash
view 'app/views/projects/edit.html.haml' do
element :advanced_settings_content
element :visibility_features_permissions_content
element :badges_settings_content
element 'advanced-settings-content'
element 'visibility-features-permissions-content'
element 'badges-settings-content'
end
view 'app/views/projects/settings/merge_requests/show.html.haml' do
element :merge_request_settings_content
element 'merge-request-settings-content'
end
view 'app/views/projects/settings/_general.html.haml' do
element :project_name_field
element :save_naming_topics_avatar_button
element 'project-name-field'
element 'save-naming-topics-avatar-button'
end
def rename_project_to(name)
@ -30,27 +30,27 @@ module QA
end
def fill_project_name(name)
fill_element :project_name_field, name
fill_element 'project-name-field', name
end
def click_save_changes
click_element :save_naming_topics_avatar_button
click_element 'save-naming-topics-avatar-button'
end
def expand_advanced_settings(&block)
expand_content(:advanced_settings_content) do
expand_content('advanced-settings-content') do
Advanced.perform(&block)
end
end
def expand_visibility_project_features_permissions(&block)
expand_content(:visibility_features_permissions_content) do
expand_content('visibility-features-permissions-content') do
VisibilityFeaturesPermissions.perform(&block)
end
end
def expand_badges_settings(&block)
expand_content(:badges_settings_content) do
expand_content('badges-settings-content') do
Component::Badges.perform(&block)
end
end

View File

@ -34,6 +34,7 @@ import {
displaySuccessfulInvitationAlert,
reloadOnInvitationSuccess,
} from '~/invite_members/utils/trigger_successful_invite_alert';
import { captureException } from '~/ci/runner/sentry_utils';
import { GROUPS_INVITATIONS_PATH, invitationsApiResponse } from '../mock_data/api_responses';
import {
propsData,
@ -52,6 +53,7 @@ import {
jest.mock('~/invite_members/utils/trigger_successful_invite_alert');
jest.mock('~/experimentation/experiment_tracking');
jest.mock('~/ci/runner/sentry_utils');
describe('InviteMembersModal', () => {
let wrapper;
@ -447,10 +449,8 @@ describe('InviteMembersModal', () => {
});
it('displays the generic error for http server error', async () => {
mockInvitationsApi(
HTTP_STATUS_INTERNAL_SERVER_ERROR,
'Request failed with status code 500',
);
const SERVER_ERROR_MESSAGE = 'Request failed with status code 500';
mockInvitationsApi(HTTP_STATUS_INTERNAL_SERVER_ERROR, SERVER_ERROR_MESSAGE);
clickInviteButton();
@ -458,6 +458,10 @@ describe('InviteMembersModal', () => {
expect(membersFormGroupInvalidFeedback()).toBe('Something went wrong');
expect(findMembersSelect().props('exceptionState')).toBe(false);
expect(captureException).toHaveBeenCalledWith({
error: new Error(SERVER_ERROR_MESSAGE),
component: wrapper.vm.$options.name,
});
});
it('displays the restricted user api message for response with bad request', async () => {

View File

@ -24,7 +24,7 @@ exports[`Project remove modal initialized matches the snapshot 1`] = `
<gl-button-stub
buttontextclasses=""
category="primary"
data-qa-selector="delete_button"
data-testid="delete-button"
icon=""
size="medium"
variant="danger"

View File

@ -6,7 +6,6 @@ import {
GITLAB_INTERNAL_EVENT_CATEGORY,
SERVICE_PING_SCHEMA,
LOAD_INTERNAL_EVENTS_SELECTOR,
USER_CONTEXT_SCHEMA,
} from '~/tracking/constants';
import * as utils from '~/tracking/utils';
import { Tracker } from '~/tracking/tracker';
@ -181,16 +180,6 @@ describe('InternalEvents', () => {
environment: 'testing',
key: 'value',
};
window.gl.snowplowStandardContext = {
schema: 'iglu:com.gitlab/gitlab_standard',
data: {
environment: 'testing',
key: 'value',
google_analytics_id: '',
source: 'gitlab-javascript',
extra: {},
},
};
});
it('should not call setDocumentTitle or page methods when window.glClient is undefined', () => {
@ -203,33 +192,11 @@ describe('InternalEvents', () => {
});
it('should call setDocumentTitle and page methods on window.glClient when it is defined', () => {
const mockStandardContext = window.gl.snowplowStandardContext;
const userContext = {
schema: USER_CONTEXT_SCHEMA,
data: mockStandardContext?.data,
};
InternalEvents.initBrowserSDK();
expect(window.glClient.setDocumentTitle).toHaveBeenCalledWith('GitLab');
expect(window.glClient.page).toHaveBeenCalledWith({
title: 'GitLab',
context: [userContext],
});
});
it('should call page method with combined standard and experiment contexts', () => {
const mockStandardContext = window.gl.snowplowStandardContext;
const userContext = {
schema: USER_CONTEXT_SCHEMA,
data: mockStandardContext?.data,
};
InternalEvents.initBrowserSDK();
expect(window.glClient.page).toHaveBeenCalledWith({
title: 'GitLab',
context: [userContext],
});
});
@ -241,16 +208,6 @@ describe('InternalEvents', () => {
expect(window.glClient.setDocumentTitle).toHaveBeenCalledWith('GitLab');
expect(window.glClient.page).toHaveBeenCalledWith({
title: 'GitLab',
context: [
{
schema: USER_CONTEXT_SCHEMA,
data: {
google_analytics_id: '',
source: 'gitlab-javascript',
extra: {},
},
},
],
});
});
});

View File

@ -268,7 +268,6 @@ RSpec.describe IssuablesHelper, feature_category: :team_planning do
markdownPreviewPath: "/#{@project.full_path}/preview_markdown?target_id=#{issue.iid}&target_type=Issue",
markdownDocsPath: '/help/user/markdown',
lockVersion: issue.lock_version,
state: issue.state,
issuableTemplateNamesPath: template_names_path(@project, issue),
initialTitleHtml: issue.title,
initialTitleText: issue.title,
@ -284,7 +283,6 @@ RSpec.describe IssuablesHelper, feature_category: :team_planning do
issuableId: issue.id,
issueType: 'issue',
isHidden: false,
sentryIssueIdentifier: nil,
zoomMeetingUrl: nil
}
@ -384,26 +382,6 @@ RSpec.describe IssuablesHelper, feature_category: :team_planning do
end
end
describe '#sentryIssueIdentifier' do
let(:issue) { create(:issue, author: user) }
before do
assign(:project, issue.project)
end
it 'sets sentryIssueIdentifier to nil with no sentry issue' do
expect(helper.issuable_initial_data(issue)[:sentryIssueIdentifier])
.to be_nil
end
it 'sets sentryIssueIdentifier to sentry_issue_identifier' do
sentry_issue = create(:sentry_issue, issue: issue)
expect(helper.issuable_initial_data(issue)[:sentryIssueIdentifier])
.to eq(sentry_issue.sentry_issue_identifier)
end
end
describe '#zoomMeetingUrl in issue' do
let(:issue) { create(:issue, author: user) }

View File

@ -297,7 +297,7 @@ RSpec.describe Emails::Profile, feature_category: :user_profile do
end
it 'has the correct subject' do
is_expected.to have_subject /^A personal access token has been revoked$/i
is_expected.to have_subject /^Your personal access token has been revoked$/i
end
it 'provides the names of the token' do
@ -325,7 +325,7 @@ RSpec.describe Emails::Profile, feature_category: :user_profile do
end
it 'has the correct subject' do
is_expected.to have_subject /^A personal access token has been revoked$/i
is_expected.to have_subject /^Your personal access token has been revoked$/i
end
it 'provides the names of the token' do

View File

@ -6,7 +6,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0
github.com/BurntSushi/toml v1.3.2
github.com/FZambia/sentinel v1.1.1
github.com/alecthomas/chroma/v2 v2.8.0
github.com/alecthomas/chroma/v2 v2.9.1
github.com/aws/aws-sdk-go v1.44.284
github.com/disintegration/imaging v1.6.2
github.com/getsentry/raven-go v0.2.0
@ -16,7 +16,7 @@ require (
github.com/gomodule/redigo v2.0.0+incompatible
github.com/gorilla/websocket v1.5.0
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/johannesboyne/gofakes3 v0.0.0-20230506070712-04da935ef877
github.com/johannesboyne/gofakes3 v0.0.0-20230914150226-f005f5cc03aa
github.com/jpillora/backoff v1.0.0
github.com/mitchellh/copystructure v1.2.0
github.com/prometheus/client_golang v1.17.0
@ -24,19 +24,19 @@ require (
github.com/redis/go-redis/v9 v9.2.1
github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a
github.com/sirupsen/logrus v1.9.3
github.com/smartystreets/goconvey v1.7.2
github.com/smartystreets/goconvey v1.8.1
github.com/stretchr/testify v1.8.4
gitlab.com/gitlab-org/gitaly/v16 v16.1.2
gitlab.com/gitlab-org/labkit v1.19.0
gitlab.com/gitlab-org/labkit v1.20.0
gocloud.dev v0.30.0
golang.org/x/image v0.7.0
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616
golang.org/x/net v0.11.0
golang.org/x/net v0.14.0
golang.org/x/oauth2 v0.9.0
golang.org/x/tools v0.8.0
golang.org/x/tools v0.12.1-0.20230825192346-2191a27a6dc5
google.golang.org/grpc v1.56.0
google.golang.org/protobuf v1.31.0
honnef.co/go/tools v0.4.3
honnef.co/go/tools v0.4.6
)
require (
@ -66,7 +66,7 @@ require (
github.com/client9/reopen v1.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dlclark/regexp2 v1.4.0 // indirect
github.com/dlclark/regexp2 v1.10.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
@ -78,7 +78,7 @@ require (
github.com/google/wire v0.5.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect
github.com/googleapis/gax-go/v2 v2.11.0 // indirect
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
github.com/gopherjs/gopherjs v1.17.2 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
@ -103,7 +103,7 @@ require (
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 // indirect
github.com/shabbyrobe/gocovmerge v0.0.0-20190829150210-3e036491d500 // indirect
github.com/shirou/gopsutil/v3 v3.21.12 // indirect
github.com/smartystreets/assertions v1.2.0 // indirect
github.com/smarty/assertions v1.15.0 // indirect
github.com/tinylib/msgp v1.1.2 // indirect
github.com/tklauser/go-sysconf v0.3.9 // indirect
github.com/tklauser/numcpus v0.3.0 // indirect
@ -112,12 +112,12 @@ require (
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.opencensus.io v0.24.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
golang.org/x/crypto v0.10.0 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.10.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.128.0 // indirect

View File

@ -759,8 +759,8 @@ github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM=
github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink=
github.com/alecthomas/chroma/v2 v2.8.0 h1:w9WJUjFFmHHB2e8mRpL9jjy3alYDlU0QLDezj1xE264=
github.com/alecthomas/chroma/v2 v2.8.0/go.mod h1:yrkMI9807G1ROx13fhe1v6PN2DDeaR73L3d+1nmYQtw=
github.com/alecthomas/chroma/v2 v2.9.1 h1:0O3lTQh9FxazJ4BYE/MOi/vDGuHn7B+6Bu902N2UZvU=
github.com/alecthomas/chroma/v2 v2.9.1/go.mod h1:4TQu7gdfuPjSh76j78ietmqh9LiurGF0EpseFXdKMBw=
github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE=
github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
@ -1078,8 +1078,8 @@ github.com/digitalocean/godo v1.78.0/go.mod h1:GBmu8MkjZmNARE7IXRPmkbbnocNN8+uBm
github.com/digitalocean/godo v1.98.0/go.mod h1:NRpFznZFvhHjBoqZAaOD3khVzsJ3EibzKqFL4R60dmA=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko=
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
@ -1488,8 +1488,9 @@ github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gophercloud/gophercloud v0.24.0/go.mod h1:Q8fZtyi5zZxPS/j9aj3sSxtvj41AdQMDwyo1myduD5c=
github.com/gophercloud/gophercloud v1.3.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
@ -1664,8 +1665,8 @@ github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHW
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
github.com/johannesboyne/gofakes3 v0.0.0-20230506070712-04da935ef877 h1:O7syWuYGzre3s73s+NkgB8e0ZvsIVhT/zxNU7V1gHK8=
github.com/johannesboyne/gofakes3 v0.0.0-20230506070712-04da935ef877/go.mod h1:AxgWC4DDX54O2WDoQO1Ceabtn6IbktjU/7bigor+66g=
github.com/johannesboyne/gofakes3 v0.0.0-20230914150226-f005f5cc03aa h1:a6Hc6Hlq6MxPNBW53/S/HnVwVXKc0nbdD/vgnQYuxG0=
github.com/johannesboyne/gofakes3 v0.0.0-20230914150226-f005f5cc03aa/go.mod h1:AxgWC4DDX54O2WDoQO1Ceabtn6IbktjU/7bigor+66g=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
@ -2111,13 +2112,13 @@ github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY=
github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
@ -2254,8 +2255,8 @@ github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaD
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
gitlab.com/gitlab-org/gitaly/v16 v16.1.2 h1:l7sltwjB/shkqlbuQzfeS3PonrQljCBKOZ2Uozk8ewA=
gitlab.com/gitlab-org/gitaly/v16 v16.1.2/go.mod h1:gfmwpE66X4lwAO/RdchFhNINSwteGFer4loUOa94nQE=
gitlab.com/gitlab-org/labkit v1.19.0 h1:7j5NOHE42R0Eu3Bj2BgfbGf4aN2HXMTmCN7H2wcqqyA=
gitlab.com/gitlab-org/labkit v1.19.0/go.mod h1:zeATDAaSBelPcPLbTTq8J3ZJEHyPTLVBM1q3nva+/W4=
gitlab.com/gitlab-org/labkit v1.20.0 h1:DGIVAdzbCR8sq2TppBvAh35wWBYIOy5dBL5wqFK3Wa8=
gitlab.com/gitlab-org/labkit v1.20.0/go.mod h1:zeATDAaSBelPcPLbTTq8J3ZJEHyPTLVBM1q3nva+/W4=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
@ -2414,8 +2415,9 @@ golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -2484,8 +2486,9 @@ golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -2580,8 +2583,9 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/oauth2 v0.0.0-20170912212905-13449ad91cb2/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -2833,8 +2837,9 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20170424234030-8be79e1e0910/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -2942,8 +2947,9 @@ golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
golang.org/x/tools v0.12.1-0.20230825192346-2191a27a6dc5 h1:Vk4mysSz+GqQK2eqgWbo4zEO89wkeAjJiFIr9bpqa8k=
golang.org/x/tools v0.12.1-0.20230825192346-2191a27a6dc5/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -3338,8 +3344,8 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
honnef.co/go/tools v0.4.3 h1:o/n5/K5gXqk8Gozvs2cnL0F2S1/g1vcGCAx2vETjITw=
honnef.co/go/tools v0.4.3/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA=
honnef.co/go/tools v0.4.6 h1:oFEHCKeID7to/3autwsWfnuv69j3NsfcXbvJKuIcep8=
honnef.co/go/tools v0.4.6/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0=
k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo=
k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ=
k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8=