Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-10-05 15:09:29 +00:00
parent c8d44b1e3b
commit 3e6c042eb0
46 changed files with 495 additions and 226 deletions

View File

@ -16,6 +16,9 @@ inherit_from:
<% if RUBY_VERSION[/^\d+\.\d+/, 0] == '3.1' %>
- ./rubocop/rubocop-ruby31.yml
<% end %>
<% if RUBY_VERSION[/^\d+\.\d+/, 0] == '3.2' %>
- ./rubocop/rubocop-ruby32.yml
<% end %>
- ./rubocop/rubocop-migrations.yml
- ./rubocop/rubocop-usage-data.yml
- ./rubocop/rubocop-code_reuse.yml

View File

@ -340,7 +340,6 @@ Layout/LineLength:
- 'app/models/incident_management/project_incident_management_setting.rb'
- 'app/models/instance_configuration.rb'
- 'app/models/integrations/asana.rb'
- 'app/models/integrations/bamboo.rb'
- 'app/models/integrations/base_chat_notification.rb'
- 'app/models/integrations/base_issue_tracker.rb'
- 'app/models/integrations/bugzilla.rb'
@ -4199,7 +4198,6 @@ Layout/LineLength:
- 'spec/models/import_failure_spec.rb'
- 'spec/models/instance_configuration_spec.rb'
- 'spec/models/integration_spec.rb'
- 'spec/models/integrations/bamboo_spec.rb'
- 'spec/models/integrations/base_chat_notification_spec.rb'
- 'spec/models/integrations/base_issue_tracker_spec.rb'
- 'spec/models/integrations/chat_message/base_message_spec.rb'

View File

@ -1,4 +0,0 @@
---
# Cop supports --autocorrect.
Lint/RedundantRequireStatement:
Enabled: false

View File

@ -118,7 +118,6 @@ Lint/UnusedMethodArgument:
- 'app/models/discussion.rb'
- 'app/models/external_issue.rb'
- 'app/models/group.rb'
- 'app/models/integrations/bamboo.rb'
- 'app/models/integrations/buildkite.rb'
- 'app/models/integrations/discord.rb'
- 'app/models/integrations/ewm.rb'

View File

@ -2177,7 +2177,6 @@ RSpec/ContextWording:
- 'spec/models/import_export_upload_spec.rb'
- 'spec/models/import_failure_spec.rb'
- 'spec/models/integration_spec.rb'
- 'spec/models/integrations/bamboo_spec.rb'
- 'spec/models/integrations/base_chat_notification_spec.rb'
- 'spec/models/integrations/chat_message/issue_message_spec.rb'
- 'spec/models/integrations/chat_message/merge_message_spec.rb'

View File

@ -4745,7 +4745,6 @@ RSpec/MissingFeatureCategory:
- 'spec/models/instance_metadata_spec.rb'
- 'spec/models/integrations/asana_spec.rb'
- 'spec/models/integrations/assembla_spec.rb'
- 'spec/models/integrations/bamboo_spec.rb'
- 'spec/models/integrations/base_issue_tracker_spec.rb'
- 'spec/models/integrations/base_slack_notification_spec.rb'
- 'spec/models/integrations/base_third_party_wiki_spec.rb'

View File

@ -78,7 +78,6 @@ Style/FormatString:
- 'app/models/diff_note.rb'
- 'app/models/diff_viewer/base.rb'
- 'app/models/integrations/asana.rb'
- 'app/models/integrations/bamboo.rb'
- 'app/models/integrations/bugzilla.rb'
- 'app/models/integrations/chat_message/pipeline_message.rb'
- 'app/models/integrations/confluence.rb'
@ -301,7 +300,6 @@ Style/FormatString:
- 'spec/lib/gitlab/config_checker/external_database_checker_spec.rb'
- 'spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb'
- 'spec/lib/gitlab/usage/service_ping_report_spec.rb'
- 'spec/models/integrations/bamboo_spec.rb'
- 'spec/models/integrations/datadog_spec.rb'
- 'spec/requests/api/graphql/project/jira_projects_spec.rb'
- 'spec/services/groups/import_export/export_service_spec.rb'

View File

@ -1,4 +0,0 @@
---
# Cop supports --autocorrect.
Style/HashSyntax:
Enabled: false

View File

@ -320,7 +320,6 @@ Style/PercentLiteralDelimiters:
- 'spec/models/group_spec.rb'
- 'spec/models/instance_configuration_spec.rb'
- 'spec/models/integration_spec.rb'
- 'spec/models/integrations/bamboo_spec.rb'
- 'spec/models/integrations/buildkite_spec.rb'
- 'spec/models/integrations/campfire_spec.rb'
- 'spec/models/integrations/jira_spec.rb'

View File

@ -6,7 +6,6 @@ Style/SingleArgumentDig:
- 'app/models/ci/build.rb'
- 'app/models/ci/build_report_result.rb'
- 'app/models/error_tracking/error_event.rb'
- 'app/models/integrations/bamboo.rb'
- 'app/serializers/codequality_degradation_entity.rb'
- 'app/services/ci/update_build_state_service.rb'
- 'ee/app/controllers/subscriptions_controller.rb'

View File

@ -14,8 +14,10 @@ import { DRAWER_Z_INDEX } from '~/lib/utils/constants';
import {
ACTIONS_I18N,
NO_ACTION,
TRUST_ACTION,
USER_ACTION_OPTIONS,
REASON_OPTIONS,
TRUST_REASON,
STATUS_OPEN,
SUCCESS_ALERT,
FAILED_ALERT,
@ -77,6 +79,16 @@ export default {
userActionOptions() {
return this.isNotCurrentUser ? USER_ACTION_OPTIONS : [NO_ACTION];
},
reasonOptions() {
if (!this.isNotCurrentUser) {
return [];
}
if (this.form.user_action === TRUST_ACTION.value) {
return [TRUST_REASON];
}
return REASON_OPTIONS;
},
},
methods: {
toggleActionsDrawer() {
@ -120,7 +132,6 @@ export default {
},
},
i18n: ACTIONS_I18N,
reasonOptions: REASON_OPTIONS,
DRAWER_Z_INDEX,
};
</script>
@ -173,7 +184,7 @@ export default {
id="reason"
v-model="form.reason"
data-testid="reason-select"
:options="$options.reasonOptions"
:options="reasonOptions"
:state="validationState.reason"
@change="validateReason"
/>

View File

@ -25,11 +25,14 @@ export const ACTIONS_I18N = {
};
export const NO_ACTION = { value: '', text: s__('AbuseReport|No action') };
export const TRUST_REASON = { value: 'trusted', text: s__(`AbuseReport|Confirmed trusted user`) };
export const TRUST_ACTION = { value: 'trust_user', text: s__('AbuseReport|Trust user') };
export const USER_ACTION_OPTIONS = [
NO_ACTION,
{ value: 'block_user', text: s__('AbuseReport|Block user') },
{ value: 'ban_user', text: s__('AbuseReport|Ban user') },
TRUST_ACTION,
{ value: 'delete_user', text: s__('AbuseReport|Delete user') },
];

View File

@ -3,6 +3,9 @@
"AlertManagementHttpIntegration",
"AlertManagementPrometheusIntegration"
],
"AmazonS3ConfigurationInterface": [
"AmazonS3ConfigurationType"
],
"BaseHeaderInterface": [
"AuditEventStreamingHeader",
"AuditEventsStreamingInstanceHeader"

View File

@ -10,6 +10,8 @@ module ResourceEvents
s_('AbuseReportEvent|Successfully blocked the user')
when 'delete_user'
s_('AbuseReportEvent|Successfully scheduled the user for deletion')
when 'trust_user'
s_('AbuseReportEvent|Successfully trusted the user')
when 'close_report'
s_('AbuseReportEvent|Successfully closed the report')
when 'ban_user_and_close_report'
@ -18,6 +20,8 @@ module ResourceEvents
s_('AbuseReportEvent|Successfully blocked the user and closed the report')
when 'delete_user_and_close_report'
s_('AbuseReportEvent|Successfully scheduled the user for deletion and closed the report')
when 'trust_user_and_close_report'
s_('AbuseReportEvent|Successfully trusted the user and closed the report')
end
end
end

View File

@ -28,14 +28,13 @@ module Integrations
non_empty_password_title: -> { s_('ProjectService|Enter new password') },
non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current password') }
validates :bamboo_url, presence: true, public_url: true, if: :activated?
validates :build_key, presence: true, if: :activated?
validates :username,
presence: true,
if: ->(service) { service.activated? && service.password }
validates :password,
presence: true,
if: ->(service) { service.activated? && service.username }
with_options if: :activated? do
validates :bamboo_url, presence: true, public_url: true
validates :build_key, presence: true
end
validates :username, presence: true, if: ->(integration) { integration.activated? && integration.password }
validates :password, presence: true, if: ->(integration) { integration.activated? && integration.username }
attr_accessor :response
@ -48,8 +47,16 @@ module Integrations
end
def help
docs_link = ActionController::Base.helpers.link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/bamboo'), target: '_blank', rel: 'noopener noreferrer'
s_('BambooService|Run CI/CD pipelines with Atlassian Bamboo. You must set up automatic revision labeling and a repository trigger in Bamboo. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
docs_link = ActionController::Base.helpers.link_to(
_('Learn more.'),
Rails.application.routes.url_helpers.help_page_url('user/project/integrations/bamboo'),
target: '_blank',
rel: 'noopener noreferrer'
)
format(
s_('BambooService|Run CI/CD pipelines with Atlassian Bamboo. You must set up automatic revision labeling and ' \
'a repository trigger in Bamboo. %{docs_link}').html_safe,
docs_link: docs_link.html_safe)
end
def self.to_param
@ -70,14 +77,16 @@ module Integrations
get_path("updateAndBuild.action", { buildKey: build_key })
end
def calculate_reactive_cache(sha, ref)
def calculate_reactive_cache(sha, _ref)
response = try_get_path("rest/api/latest/result/byChangeset/#{sha}")
{ build_page: read_build_page(response), commit_status: read_commit_status(response) }
end
def avatar_url
ActionController::Base.helpers.image_path('illustrations/third-party-logos/integrations-logos/atlassian-bamboo.svg')
ActionController::Base.helpers.image_path(
'illustrations/third-party-logos/integrations-logos/atlassian-bamboo.svg'
)
end
private
@ -116,7 +125,7 @@ module Integrations
if result.blank?
'Pending'
else
result.dig('buildState')
result['buildState']
end
return :error unless status.present?

View File

@ -16,7 +16,9 @@ module ResourceEvents
close_report: 4,
ban_user_and_close_report: 5,
block_user_and_close_report: 6,
delete_user_and_close_report: 7
delete_user_and_close_report: 7,
trust_user: 8,
trust_user_and_close_report: 9
}
enum reason: {
@ -28,7 +30,8 @@ module ResourceEvents
copyright: 6,
malware: 7,
other: 8,
unconfirmed: 9
unconfirmed: 9,
trusted: 10
}
def success_message

View File

@ -271,6 +271,7 @@ class User < MainClusterwide::ApplicationRecord
has_many :bulk_imports
has_many :custom_attributes, class_name: 'UserCustomAttribute'
has_one :trusted_with_spam_attribute, -> { UserCustomAttribute.trusted_with_spam }, class_name: 'UserCustomAttribute'
has_many :callouts, class_name: 'Users::Callout'
has_many :group_callouts, class_name: 'Users::GroupCallout'
has_many :project_callouts, class_name: 'Users::ProjectCallout'
@ -2223,8 +2224,8 @@ class User < MainClusterwide::ApplicationRecord
}
end
def allow_possible_spam?
custom_attributes.by_key(UserCustomAttribute::ALLOW_POSSIBLE_SPAM).exists?
def trusted?
trusted_with_spam_attribute.present?
end
def namespace_commit_email_for_namespace(namespace)

View File

@ -10,13 +10,14 @@ class UserCustomAttribute < ApplicationRecord
scope :by_user_id, ->(user_id) { where(user_id: user_id) }
scope :by_updated_at, ->(updated_at) { where(updated_at: updated_at) }
scope :arkose_sessions, -> { by_key('arkose_session') }
scope :trusted_with_spam, -> { by_key(TRUSTED_BY) }
BLOCKED_BY = 'blocked_by'
UNBLOCKED_BY = 'unblocked_by'
ARKOSE_RISK_BAND = 'arkose_risk_band'
AUTO_BANNED_BY_ABUSE_REPORT_ID = 'auto_banned_by_abuse_report_id'
AUTO_BANNED_BY_SPAM_LOG_ID = 'auto_banned_by_spam_log_id'
ALLOW_POSSIBLE_SPAM = 'allow_possible_spam'
TRUSTED_BY = 'trusted_by'
IDENTITY_VERIFICATION_PHONE_EXEMPT = 'identity_verification_phone_exempt'
class << self
@ -50,6 +51,17 @@ class UserCustomAttribute < ApplicationRecord
return unless spam_log
custom_attribute = { user_id: spam_log.user_id, key: AUTO_BANNED_BY_SPAM_LOG_ID, value: spam_log.id }
upsert_custom_attributes([custom_attribute])
end
def set_trusted_by(user:, trusted_by:)
return unless user && trusted_by
custom_attribute = {
user_id: user.id,
key: UserCustomAttribute::TRUSTED_BY,
value: "#{trusted_by.username}/#{trusted_by.id}+#{Time.current}"
}
upsert_custom_attributes([custom_attribute])
end

View File

@ -42,6 +42,7 @@ module Admin
when :block_user then block_user
when :delete_user then delete_user
when :close_report then close_report
when :trust_user then trust_user
end
end
@ -66,6 +67,10 @@ module Admin
success
end
def trust_user
Users::TrustService.new(current_user).execute(abuse_report.user)
end
def close_similar_open_reports
# admins see the abuse report and other open reports for the same user in one page
# hence, if the request is to close the report, close other open reports for the same user too

View File

@ -90,7 +90,7 @@ module Spam
end
def allow_possible_spam?
target.allow_possible_spam?(user) || user.allow_possible_spam?
target.allow_possible_spam?(user) || user.trusted?
end
def spamcheck_client

View File

@ -1,18 +0,0 @@
# frozen_string_literal: true
module Users
class AllowPossibleSpamService < BaseService
def initialize(current_user)
@current_user = current_user
end
def execute(user)
custom_attribute = {
user_id: user.id,
key: UserCustomAttribute::ALLOW_POSSIBLE_SPAM,
value: "#{current_user.username}/#{current_user.id}+#{Time.current}"
}
UserCustomAttribute.upsert_custom_attributes([custom_attribute])
end
end
end

View File

@ -1,13 +1,14 @@
# frozen_string_literal: true
module Users
class DisallowPossibleSpamService < BaseService
class TrustService < BaseService
def initialize(current_user)
@current_user = current_user
end
def execute(user)
user.custom_attributes.by_key(UserCustomAttribute::ALLOW_POSSIBLE_SPAM).delete_all
UserCustomAttribute.set_trusted_by(user: user, trusted_by: @current_user)
success
end
end
end

View File

@ -0,0 +1,14 @@
# frozen_string_literal: true
module Users
class UntrustService < BaseService
def initialize(current_user)
@current_user = current_user
end
def execute(user)
user.trusted_with_spam_attribute.delete
success
end
end
end

View File

@ -7,7 +7,7 @@
= f.select :first_day_of_week, first_day_of_week_choices, {}, class: 'form-control'
.form-text.text-muted
= _('Default first day of the week in calendars and date pickers.')
= link_to _('Learn more.'), help_page_path('administration/settings/index.md', anchor: 'change-the-default-first-day-of-the-week'), target: '_blank', rel: 'noopener noreferrer'
= link_to _('Learn more.'), help_page_path('administration/settings/localization.md', anchor: 'change-the-default-first-day-of-the-week'), target: '_blank', rel: 'noopener noreferrer'
.form-group
= f.label :time_tracking, _('Time tracking'), class: 'label-bold'

View File

@ -37,6 +37,7 @@ audit events to external destinations.
| [`allow_committer_approval_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/102256) | Event triggered on updating prevent merge request approval from committers from group merge request setting | **{check-circle}** Yes | **{check-circle}** Yes | `compliance_management` | GitLab [15.6](https://gitlab.com/gitlab-org/gitlab/-/issues/373949) |
| [`allow_merge_on_skipped_pipeline_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83922) | There is a project setting which toggles the ability to merge when a pipeline is skipped. This audit event tracks changes to that setting. This MR adds a setting to allow this (like previous GitLab versions). | **{check-circle}** Yes | **{check-circle}** Yes | `continuous_integration` | GitLab [14.10](https://gitlab.com/gitlab-org/gitlab/-/issues/301124) |
| [`allow_overrides_to_approver_list_per_merge_request_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/102256) | Event triggered on updating prevent users from modifying MR approval rules in merge requests from group merge request setting | **{check-circle}** Yes | **{check-circle}** Yes | `compliance_management` | GitLab [15.6](https://gitlab.com/gitlab-org/gitlab/-/issues/373949) |
| [`amazon_s3_configuration_created`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132443) | Triggered when Amazon S3 configuration for audit events streaming is created | **{check-circle}** Yes | **{check-circle}** Yes | `audit_events` | GitLab [16.5](https://gitlab.com/gitlab-org/gitlab/-/issues/423229) |
| [`application_setting_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/124639) | Triggered when Application setting is updated | **{check-circle}** Yes | **{check-circle}** Yes | `system_access` | GitLab [16.3](https://gitlab.com/gitlab-org/gitlab/-/issues/282428) |
| [`approval_rule_created`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89939) | Triggered when a merge request approval rule is created | **{check-circle}** Yes | **{check-circle}** Yes | `source_code_management` | GitLab [15.2](https://gitlab.com/gitlab-org/gitlab/-/issues/363092) |
| [`approval_rule_deleted`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82297) | Triggered on successful approval rule deletion | **{check-circle}** Yes | **{check-circle}** Yes | `source_code_management` | GitLab [14.9](https://gitlab.com/gitlab-org/gitlab/-/issues/329514) |

View File

@ -32,13 +32,15 @@ To find out more about reporting abuse, see
## Resolving abuse reports
> **Trust user** [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131102) in GitLab 16.4.
To access abuse reports:
1. On the left sidebar, select **Search or go to**.
1. Select **Admin Area**.
1. Select **Abuse Reports**.
There are 3 ways to resolve an abuse report, with a button for each method:
There are four ways to resolve an abuse report, with a button for each method:
- Remove user & report. This:
- [Deletes the reported user](../user/profile/account/delete_account.md) from the
@ -48,6 +50,9 @@ There are 3 ways to resolve an abuse report, with a button for each method:
- Remove report. This:
- Removes the abuse report from the list.
- Removes access restrictions for the reported user.
- Trust user. This:
- Allows the user to create issues, notes, snippets, and merge requests without being blocked for spam.
- Prevents abuse reports from being created for this user.
The following is an example of the **Abuse Reports** page:

View File

@ -1,18 +1,16 @@
---
stage: Create
group: Source Code
stage: none
group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index
---
# Admin Area settings **(FREE SELF)**
# Update your Admin Area settings **(FREE SELF)**
As an administrator of a GitLab self-managed instance, you can manage the behavior of your
deployment.
The **Admin Area** is not accessible on GitLab.com, and settings can only be changed by the
GitLab.com administrators. For the settings and limits on the GitLab.com instance,
read [GitLab.com settings](../../user/gitlab_com/index.md).
Use **Settings** to control settings across the instance.
## Access the Admin Area
@ -21,23 +19,3 @@ To access the **Admin Area**:
1. Sign in to your GitLab instance as an administrator.
1. On the left sidebar, select **Search or go to**.
1. Select **Admin Area**.
## Change the default first day of the week
You can change the [Default first day of the week](../../user/profile/preferences.md)
for the entire GitLab instance:
1. On the left sidebar, select **Search or go to**.
1. Select **Admin Area**.
1. Select **Settings > Preferences**.
1. Scroll to the **Localization** section, and select your desired first day of the week.
## Change the default language
You can change the [Default language](../../user/profile/preferences.md)
for the entire GitLab instance:
1. On the left sidebar, select **Search or go to**.
1. Select **Admin Area**.
1. Select **Settings > Preferences**.
1. Scroll to the **Localization** section, and select your desired default language.

View File

@ -0,0 +1,31 @@
---
stage: none
group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index
---
# Localization **(FREE SELF)**
As an administrator of a GitLab self-managed instance, you can manage the behavior of your
deployment.
## Change the default first day of the week
You can change the [Default first day of the week](../../user/profile/preferences.md)
for the entire GitLab instance:
1. On the left sidebar, select **Search or go to**.
1. Select **Admin Area**.
1. Select **Settings > Preferences**.
1. Scroll to the **Localization** section, and select your desired first day of the week.
## Change the default language
You can change the [Default language](../../user/profile/preferences.md)
for the entire GitLab instance:
1. On the left sidebar, select **Search or go to**.
1. Select **Admin Area**.
1. Select **Settings > Preferences**.
1. Scroll to the **Localization** section, and select your desired default language.

View File

@ -0,0 +1,24 @@
---
stage: none
group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index
---
# Rate limits
You can change network settings to limit the rate of connections with your instance.
- [Deprecated API rate limits](deprecated_api_rate_limits.md)
- [Git LFS](git_lfs_rate_limits.md)
- [Git SSH operations](rate_limits_on_git_ssh_operations.md)
- [Incident management](incident_management_rate_limits.md)
- [Issue creation](rate_limit_on_issues_creation.md)
- [Note creation](rate_limit_on_notes_creation.md)
- [Package Registry](package_registry_rate_limits.md)
- [Pipeline creation](rate_limit_on_pipelines_creation.md)
- [Projects API](rate_limit_on_projects_api.md)
- [Raw endpoints](rate_limits_on_raw_endpoints.md)
- [Repository files API](files_api_rate_limits.md)
- [User and IP](user_and_ip_rate_limits.md)
- [Users API](rate_limit_on_users_api.md)

View File

@ -1274,6 +1274,30 @@ Input type: `AlertTodoCreateInput`
| <a id="mutationalerttodocreateissue"></a>`issue` | [`Issue`](#issue) | Issue created after mutation. |
| <a id="mutationalerttodocreatetodo"></a>`todo` | [`Todo`](#todo) | To-do item after mutation. |
### `Mutation.amazonS3ConfigurationCreate`
Input type: `AmazonS3ConfigurationCreateInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationamazons3configurationcreateaccesskeyxid"></a>`accessKeyXid` | [`String!`](#string) | Access key ID of the Amazon S3 account. |
| <a id="mutationamazons3configurationcreateawsregion"></a>`awsRegion` | [`String!`](#string) | AWS region where the bucket is created. |
| <a id="mutationamazons3configurationcreatebucketname"></a>`bucketName` | [`String!`](#string) | Name of the bucket where the audit events would be logged. |
| <a id="mutationamazons3configurationcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationamazons3configurationcreategrouppath"></a>`groupPath` | [`ID!`](#id) | Group path. |
| <a id="mutationamazons3configurationcreatename"></a>`name` | [`String`](#string) | Destination name. |
| <a id="mutationamazons3configurationcreatesecretaccesskey"></a>`secretAccessKey` | [`String!`](#string) | Secret access key of the Amazon S3 account. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationamazons3configurationcreateamazons3configuration"></a>`amazonS3Configuration` | [`AmazonS3ConfigurationType`](#amazons3configurationtype) | configuration created. |
| <a id="mutationamazons3configurationcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationamazons3configurationcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
### `Mutation.approveDeployment`
Input type: `ApproveDeploymentInput`
@ -13290,6 +13314,21 @@ An endpoint and credentials used to accept Prometheus alerts for a project.
| <a id="alertmanagementprometheusintegrationtype"></a>`type` | [`AlertManagementIntegrationType!`](#alertmanagementintegrationtype) | Type of integration. |
| <a id="alertmanagementprometheusintegrationurl"></a>`url` | [`String`](#string) | Endpoint which accepts alert notifications. |
### `AmazonS3ConfigurationType`
Stores Amazon S3 configurations.
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="amazons3configurationtypeaccesskeyxid"></a>`accessKeyXid` | [`String!`](#string) | Access key ID of the Amazon S3 account. |
| <a id="amazons3configurationtypeawsregion"></a>`awsRegion` | [`String!`](#string) | AWS region where the bucket is created. |
| <a id="amazons3configurationtypebucketname"></a>`bucketName` | [`String!`](#string) | Name of the bucket where the audit events would be logged. |
| <a id="amazons3configurationtypegroup"></a>`group` | [`Group!`](#group) | Group the configuration belongs to. |
| <a id="amazons3configurationtypeid"></a>`id` | [`ID!`](#id) | ID of the configuration. |
| <a id="amazons3configurationtypename"></a>`name` | [`String!`](#string) | Name of the external destination to send audit events to. |
### `ApiFuzzingCiConfiguration`
Data associated with configuring API fuzzing scans in GitLab CI.
@ -30275,6 +30314,22 @@ Implementations:
| <a id="alertmanagementintegrationtype"></a>`type` | [`AlertManagementIntegrationType!`](#alertmanagementintegrationtype) | Type of integration. |
| <a id="alertmanagementintegrationurl"></a>`url` | [`String`](#string) | Endpoint which accepts alert notifications. |
#### `AmazonS3ConfigurationInterface`
Implementations:
- [`AmazonS3ConfigurationType`](#amazons3configurationtype)
##### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="amazons3configurationinterfaceaccesskeyxid"></a>`accessKeyXid` | [`String!`](#string) | Access key ID of the Amazon S3 account. |
| <a id="amazons3configurationinterfaceawsregion"></a>`awsRegion` | [`String!`](#string) | AWS region where the bucket is created. |
| <a id="amazons3configurationinterfacebucketname"></a>`bucketName` | [`String!`](#string) | Name of the bucket where the audit events would be logged. |
| <a id="amazons3configurationinterfaceid"></a>`id` | [`ID!`](#id) | ID of the configuration. |
| <a id="amazons3configurationinterfacename"></a>`name` | [`String!`](#string) | Name of the external destination to send audit events to. |
#### `BaseHeaderInterface`
Implementations:

View File

@ -0,0 +1,114 @@
---
stage: Manage
group: Import and Integrate
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# AWS CodePipeline **(FREE SAAS)**
> [Introduced](https://gitlab.com/gitlab-com/alliances/aws/wip/aws-cs-collab/aws-gitlab-collaboration/-/issues/25) in GitLab 16.5.
You can use your GitLab project to build, test, and deploy code changes using [AWS CodePipeline](https://aws.amazon.com/codepipeline/). To do so, you use:
- AWS CodeStar Connections to connect your GitLab.com account to AWS.
- That connection to automatically start a pipeline based on changes to your code.
## Create a connection from AWS CodePipeline to GitLab
Prerequisites:
- You must have the Owner role on the GitLab project that you are connecting with AWS CodePipeline.
- You must have the appropriate permissions to create a connection in AWS.
- You must use a supported AWS region. Unsupported regions (also listed in the [AWS documentation](https://docs.aws.amazon.com/codepipeline/latest/userguide/connections-gitlab.html)) are:
- Asia Pacific (Hong Kong).
- Africa (Cape Town).
- Middle East (Bahrain).
- Europe (Zurich).
- AWS GovCloud (US-West and US-East).
To create a connection to a project on GitLab.com, you can use either the AWS Management Console, or the AWS Command Line Interface (AWS CLI).
### Use the AWS Management Console
To connect a new or existing pipeline in AWS CodePipeline with GitLab.com, first authorize the AWS connection to use your GitLab account.
1. Sign in to the AWS Management Console, and open the [AWS Developer Tools console](https://console.aws.amazon.com/codesuite/settings/connections).
1. Select **Settings** > **Connections** > **Create connection**.
1. In **Select a provider**, select **GitLab**.
1. In **Connection name**, enter the name for the connection that you want to create and select **Connect to GitLab**.
1. In the GitLab sign-in page, enter your credentials and select **Sign in**.
1. An authorization page displays with a message requesting authorization for the connection to access your GitLab account. Select **Authorize**.
1. The browser returns to the connections console page. In the **Create GitLab connection** section, the new connection is shown in **Connection name**.
1. Select **Connect to GitLab**. After the connection is created successfully, a success banner displays. The connection details are shown on the **Connection settings** page.
Now you've connected AWS CodeSuite to GitLab.com, you can create or edit a pipeline in AWS CodePipeline that leverages your GitLab projects.
1. Sign in to the [AWS CodePipeline console](https://console.aws.amazon.com/codesuite/codepipeline/start).
1. Create or edit a pipeline:
- If you are creating a pipeline:
- Complete the fields in the first screen and select **Next**.
- On the **Source** page, in the **Source Provider** section, select **GitLab**.
- If you are editing an existing pipeline:
- Select **Edit** > **Edit stage** to add or edit your source action.
- On the **Edit action** page, in the **Action name** section, enter the name for your action.
- In **Action provider**, select **GitLab**.
1. In **Connection**, select the connection you created earlier.
1. In **Repository name**, to choose the name of your GitLab project, specify the full project path with the namespace and all subgroups.
For example, for a group-level project, enter the project name in the following format: `group-name/subgroup-name/project-name`.
The project path with the namespace is in the URL in GitLab. Do not copy URLs from the Web IDE or raw views as they contain other special URL segments.
You can also pick an option from the dialog, or type a new path manually.
For more information about the:
- Path and namespace, see the `path_with_namespace` field in the [projects API](../../../api/projects.md#get-single-project).
- Namespace in GitLab, see [namespaces](../../namespace/index.md).
1. In **Branch name**, select the branch where you want your pipeline to detect source changes.
If the branch name does not populate automatically, this might be because of one of the following:
- You do not have the Owner role for the project.
- The project name is not valid.
- The connection used does not have access to the project.
1. In **Output artifact format**, select the format for your artifacts. To store:
- Output artifacts from the GitLab action using the default method, select **CodePipeline default**. The action accesses the files from the GitLab repository and
stores the artifacts in a ZIP file in the pipeline artifact store.
- A JSON file that contains a URL reference to the repository so that downstream actions can perform Git commands directly, select **Full clone**. This option can only be used
by CodeBuild downstream actions. To choose this option:
- [Update the permissions for your CodeBuild project service role](https://docs.aws.amazon.com/codepipeline/latest/userguide/troubleshooting.html#codebuild-role-connections).
- Follow the [AWS CodePipeline tutorial on how to use full clone with a GitHub pipeline source](https://docs.aws.amazon.com/codepipeline/latest/userguide/tutorials-github-gitclone.html).
1. Save the source action and continue.
### Use the AWS CLI
To use the AWS CLI to create a connection:
- Use the `create-connection` command.
- Go to the AWS Console to authenticate with your GitLab.com account.
- Connect your GitLab project to AWS CodePipeline.
To use the `create-connection` command:
1. Open a terminal (Linux, macOS, or Unix) or command prompt (Windows). Use the AWS CLI to run the `create-connection` command,
specifying the `--provider-type` and `--connection-name` for your connection. In this example, the third-party provider name is
`GitLab` and the specified connection name is `MyConnection`.
```shell
aws codestar-connections create-connection --provider-type GitLab --connection-name MyConnection
```
If successful, this command returns the connection's Amazon Resource Name (ARN) information. For example:
```json
{
"ConnectionArn": "arn:aws:codestar-connections:us-west-2:account_id:connection/aEXAMPLE-8aad-4d5d-8878-dfcab0bc441f"
}
```
1. The new connection is created with a `PENDING` status by default. Use the console to change the connection's status to `AVAILABLE`.
1. [Use the AWS Console to complete the connection](#use-the-aws-management-console). Make sure you select your pending GitLab connection. Do not select **Create connection**.
## Related topics
- [Announcement that AWS CodePipeline supports GitLab](https://aws.amazon.com/about-aws/whats-new/2023/08/aws-codepipeline-supports-gitlab/)
- [GitLab connections - AWS CodePipeline](https://docs.aws.amazon.com/codepipeline/latest/userguide/connections-gitlab.html)
- [Create a connection to GitLab - Developer Tools console](https://docs.aws.amazon.com/dtconsole/latest/userguide/connections-create-gitlab.html)
- [CodeStarSourceConnection for Bitbucket, GitHub, GitHub Enterprise Server, and GitLab actions - AWS CodePipeline](https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodestarConnectionSource.html)

View File

@ -0,0 +1,13 @@
# frozen_string_literal: true
module Gitlab
module Checks
module Security
class PolicyCheck < BaseSingleChecker
def validate!; end
end
end
end
end
Gitlab::Checks::Security::PolicyCheck.prepend_mod

View File

@ -54,6 +54,7 @@ module Gitlab
Gitlab::Checks::PushCheck.new(self).validate!
Gitlab::Checks::BranchCheck.new(self).validate!
Gitlab::Checks::TagCheck.new(self).validate!
Gitlab::Checks::Security::PolicyCheck.new(self).validate!
end
def commits_check

View File

@ -1,105 +0,0 @@
# frozen_string_literal: true
require 'set'
module Gitlab
module Pages
class CacheControl
include Gitlab::Utils::StrongMemoize
EXPIRE = 12.hours
# To avoid delivering expired deployment URL in the cached payload,
# use a longer expiration time in the deployment URL
DEPLOYMENT_EXPIRATION = (EXPIRE + 12.hours)
SETTINGS_CACHE_KEY = 'pages_domain_for_%{type}_%{id}'
PAYLOAD_CACHE_KEY = '%{settings_cache_key}_%{settings_hash}'
class << self
def for_domain(domain_id)
new(type: :domain, id: domain_id)
end
def for_namespace(namespace_id)
new(type: :namespace, id: namespace_id)
end
end
def initialize(type:, id:)
raise(ArgumentError, "type must be :namespace or :domain") unless %i[namespace domain].include?(type)
@type = type
@id = id
end
def cache_key
strong_memoize(:payload_cache_key) do
cache_settings_hash!
payload_cache_key_for(settings_hash)
end
end
# Invalidates the cache.
#
# Since rails nodes and sidekiq nodes have different application settings,
# and the invalidation happens in a sidekiq node, we have to use the
# cached settings hash to build the payload cache key to be invalidated.
def clear_cache
keys = cached_settings_hashes
.map { |hash| payload_cache_key_for(hash) }
.push(settings_cache_key)
::Gitlab::AppLogger.info(
message: 'clear pages cache',
pages_keys: keys,
pages_type: @type,
pages_id: @id
)
Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
Rails.cache.delete_multi(keys)
end
end
private
# Since rails nodes and sidekiq nodes have different application settings,
# we cache the application settings hash when creating the payload cache
# so we can use these values to invalidate the cache in a sidekiq node later.
def cache_settings_hash!
cached = cached_settings_hashes.to_set
Rails.cache.write(settings_cache_key, cached.add(settings_hash))
end
def cached_settings_hashes
Rails.cache.read(settings_cache_key) || []
end
def payload_cache_key_for(settings_hash)
PAYLOAD_CACHE_KEY % {
settings_cache_key: settings_cache_key,
settings_hash: settings_hash
}
end
def settings_cache_key
strong_memoize(:settings_cache_key) do
SETTINGS_CACHE_KEY % { type: @type, id: @id }
end
end
def settings_hash
strong_memoize(:settings_hash) do
values = ::Gitlab.config.pages.dup
values['app_settings'] = ::Gitlab::CurrentSettings.attributes.slice(
'force_pages_access_control'
)
::Digest::SHA256.hexdigest(values.inspect)
end
end
end
end
end

View File

@ -2239,6 +2239,12 @@ msgstr ""
msgid "AbuseReportEvent|Successfully scheduled the user for deletion and closed the report"
msgstr ""
msgid "AbuseReportEvent|Successfully trusted the user"
msgstr ""
msgid "AbuseReportEvent|Successfully trusted the user and closed the report"
msgstr ""
msgid "AbuseReports|%{reportedUser} reported for %{category} by %{count} users"
msgstr ""
@ -2308,6 +2314,9 @@ msgstr ""
msgid "AbuseReport|Confirmed spam"
msgstr ""
msgid "AbuseReport|Confirmed trusted user"
msgstr ""
msgid "AbuseReport|Confirmed violation of a copyright or a trademark"
msgstr ""
@ -2428,6 +2437,9 @@ msgstr ""
msgid "AbuseReport|Tier"
msgstr ""
msgid "AbuseReport|Trust user"
msgstr ""
msgid "AbuseReport|Verification"
msgstr ""

View File

@ -2,6 +2,7 @@
# Ruby 3.1.
#
# After the transition has been completed:
# * Enable all disabled cops and resolve the offenses.
# * Move all configuration which enabled or tweaked cops to .rubocop.yml.
# * Remove all remaining configuration.

View File

@ -0,0 +1,15 @@
# RuboCop configuration adjustments during the transition time from Ruby 3.1 to
# Ruby 3.2.
#
# After the transition has been completed:
# * Enable all disabled cops and resolve the offenses.
# * Move all configuration which enabled or tweaked cops to .rubocop.yml.
# * Remove all remaining configuration.
# Short-hand Hash syntax does not work prior 3.1.
Style/HashSyntax:
EnforcedShorthandSyntax: never
# With 3.2+ `require 'set'` is no longer needed as it's always loaded.
Lint/RedundantRequireStatement:
Enabled: false

View File

@ -48,6 +48,15 @@ FactoryBot.define do
after(:build) { |user, _| user.ban! }
end
trait :trusted do
after(:create) do |user, _|
user.custom_attributes.create!(
key: UserCustomAttribute::TRUSTED_BY,
value: "placeholder"
)
end
end
trait :ldap_blocked do
after(:build) { |user, _| user.ldap_block! }
end

View File

@ -17,6 +17,9 @@ import {
ERROR_MESSAGE,
NO_ACTION,
USER_ACTION_OPTIONS,
TRUST_ACTION,
TRUST_REASON,
REASON_OPTIONS,
} from '~/admin/abuse_report/constants';
import { mockAbuseReport } from '../mock_data';
@ -40,10 +43,11 @@ describe('ReportActions', () => {
const setCloseReport = (close) => wrapper.findByTestId('close').find('input').setChecked(close);
const setSelectOption = (id, value) =>
wrapper.findByTestId(`${id}-select`).find(`option[value=${value}]`).setSelected();
const selectAction = (action) => setSelectOption('action', action);
const selectAction = (chosenAction) => setSelectOption('action', chosenAction);
const selectReason = (reason) => setSelectOption('reason', reason);
const setComment = (comment) => wrapper.findByTestId('comment').find('input').setValue(comment);
const submitForm = () => wrapper.findByTestId('submit-button').vm.$emit('click');
const findReasonOptions = () => wrapper.findByTestId('reason-select');
const createComponent = (props = {}) => {
wrapper = mountExtended(ReportActions, {
@ -79,8 +83,8 @@ describe('ReportActions', () => {
expect(options).toHaveLength(USER_ACTION_OPTIONS.length);
USER_ACTION_OPTIONS.forEach((action, index) => {
expect(options.at(index).text()).toBe(action.text);
USER_ACTION_OPTIONS.forEach((userAction, index) => {
expect(options.at(index).text()).toBe(userAction.text);
});
});
});
@ -100,6 +104,51 @@ describe('ReportActions', () => {
});
});
describe('reasons', () => {
beforeEach(() => {
clickActionsButton();
});
it('shows all non-trust reasons by default', () => {
const reasons = findReasonOptions().findAll('option');
expect(reasons).toHaveLength(REASON_OPTIONS.length);
REASON_OPTIONS.forEach((reason, index) => {
expect(reasons.at(index).text()).toBe(reason.text);
});
});
describe('when user selects any non-trust action', () => {
it('shows non-trust reasons', () => {
const reasonLength = REASON_OPTIONS.length;
let reasons;
USER_ACTION_OPTIONS.forEach((userAction) => {
if (userAction !== TRUST_ACTION && userAction !== NO_ACTION) {
selectAction(userAction.value);
reasons = findReasonOptions().findAll('option');
expect(reasons).toHaveLength(reasonLength);
}
});
});
});
describe('when user selects "Trust user"', () => {
beforeEach(() => {
selectAction(TRUST_ACTION.value);
});
it('only shows "Confirmed trusted user" reason', () => {
const reasons = findReasonOptions().findAll('option');
expect(reasons).toHaveLength(1);
expect(reasons.at(0).text()).toBe(TRUST_REASON.text);
});
});
});
describe('when clicking the actions button', () => {
beforeEach(() => {
clickActionsButton();

View File

@ -116,7 +116,7 @@ RSpec.describe Integrations::Bamboo, :use_clean_rails_memory_store_caching, feat
is_expected.to eq('http://gitlab.com/bamboo/browse/42')
end
context 'bamboo_url has trailing slash' do
context 'when bamboo_url has trailing slash' do
let(:bamboo_url) { 'http://gitlab.com/bamboo/' }
it 'returns a build URL' do
@ -198,7 +198,8 @@ RSpec.describe Integrations::Bamboo, :use_clean_rails_memory_store_caching, feat
context 'when Bamboo API returns an array of results and we only consider the last one' do
let(:bamboo_response_template) do
%q({"results":{"results":{"size":"2","result":[{"buildState":"%{build_state}","planResultKey":{"key":"41"}},{"buildState":"%{build_state}","planResultKey":{"key":"42"}}]}}})
'{"results":{"results":{"size":"2","result":[{"buildState":"%{build_state}","planResultKey":{"key":"41"}}, ' \
'{"buildState":"%{build_state}","planResultKey":{"key":"42"}}]}}}'
end
it_behaves_like 'reactive cache calculation'
@ -207,7 +208,9 @@ RSpec.describe Integrations::Bamboo, :use_clean_rails_memory_store_caching, feat
describe '#avatar_url' do
it 'returns the avatar image path' do
expect(subject.avatar_url).to eq(ActionController::Base.helpers.image_path('illustrations/third-party-logos/integrations-logos/atlassian-bamboo.svg'))
expect(subject.avatar_url).to eq(ActionController::Base.helpers.image_path(
'illustrations/third-party-logos/integrations-logos/atlassian-bamboo.svg'
))
end
end
@ -228,11 +231,11 @@ RSpec.describe Integrations::Bamboo, :use_clean_rails_memory_store_caching, feat
status: status,
headers: { 'Content-Type' => 'application/json' },
body: body
).with(basic_auth: %w(mic password))
).with(basic_auth: %w[mic password])
end
def bamboo_response(build_state: 'success')
# reference: https://docs.atlassian.com/atlassian-bamboo/REST/6.2.5/#d2e786
bamboo_response_template % { build_state: build_state }
format(bamboo_response_template, build_state: build_state)
end
end

View File

@ -6120,25 +6120,23 @@ RSpec.describe User, feature_category: :user_profile do
end
end
describe '#allow_possible_spam?' do
describe '#trusted?' do
context 'when no custom attribute is set' do
it 'is false' do
expect(user.allow_possible_spam?).to be_falsey
it 'is falsey' do
expect(user.trusted?).to be_falsey
end
end
context 'when the custom attribute is set' do
before do
user.custom_attributes.upsert_custom_attributes(
[{
user_id: user.id,
key: UserCustomAttribute::ALLOW_POSSIBLE_SPAM,
value: "test"
}])
user.custom_attributes.create!(
key: UserCustomAttribute::TRUSTED_BY,
value: "test"
)
end
it '#allow_possible_spam? is true' do
expect(user.allow_possible_spam?).to be_truthy
it 'is truthy' do
expect(user.trusted?).to be_truthy
end
end
end

View File

@ -210,6 +210,43 @@ RSpec.describe Admin::AbuseReports::ModerateUserService, feature_category: :inst
end
end
describe 'when trusting the user' do
let(:action) { 'trust_user' }
it 'calls the Users::TrustService method' do
expect_next_instance_of(Users::TrustService, admin) do |service|
expect(service).to receive(:execute).with(abuse_report.user).and_return(status: :success)
end
subject
end
context 'when not closing the report' do
let(:close) { false }
it_behaves_like 'does not close the report'
it_behaves_like 'records an event', action: 'trust_user'
end
context 'when closing the report' do
it_behaves_like 'closes the report'
it_behaves_like 'records an event', action: 'trust_user_and_close_report'
end
context 'when trusting the user fails' do
before do
allow_next_instance_of(Users::TrustService) do |service|
allow(service).to receive(:execute).with(abuse_report.user)
.and_return(status: :error, message: 'Trusting the user failed')
end
end
it_behaves_like 'returns an error response', 'Trusting the user failed'
it_behaves_like 'does not close the report'
it_behaves_like 'does not record an event'
end
end
describe 'when only closing the report' do
let(:action) { '' }

View File

@ -31,7 +31,7 @@ RSpec.describe Spam::SpamVerdictService, feature_category: :instance_resiliency
end
let(:check_for_spam) { true }
let_it_be(:user) { create(:user) }
let_it_be_with_reload(:user) { create(:user) }
let_it_be(:issue) { create(:issue, author: user) }
let_it_be(:snippet) { create(:personal_snippet, :public, author: user) }
@ -136,15 +136,9 @@ RSpec.describe Spam::SpamVerdictService, feature_category: :instance_resiliency
end
end
context 'if allow_possible_spam user custom attribute is set' do
context 'if user is trusted to create possible spam' do
before do
UserCustomAttribute.upsert_custom_attributes(
[{
user_id: user.id,
key: 'allow_possible_spam',
value: 'does not matter'
}]
)
user.custom_attributes.create!(key: 'trusted_by', value: 'does not matter')
end
context 'and a service returns a verdict that should be overridden' do

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Users::AllowPossibleSpamService, feature_category: :user_management do
RSpec.describe Users::TrustService, feature_category: :user_management do
let_it_be(:current_user) { create(:admin) }
subject(:service) { described_class.new(current_user) }
@ -18,7 +18,7 @@ RSpec.describe Users::AllowPossibleSpamService, feature_category: :user_manageme
operation
user.reload
expect(user.custom_attributes.by_key(UserCustomAttribute::ALLOW_POSSIBLE_SPAM)).to be_present
expect(user.custom_attributes.by_key(UserCustomAttribute::TRUSTED_BY)).to be_present
end
end
end

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Users::DisallowPossibleSpamService, feature_category: :user_management do
RSpec.describe Users::UntrustService, feature_category: :user_management do
let_it_be(:current_user) { create(:admin) }
subject(:service) { described_class.new(current_user) }
@ -16,19 +16,19 @@ RSpec.describe Users::DisallowPossibleSpamService, feature_category: :user_manag
UserCustomAttribute.upsert_custom_attributes(
[{
user_id: user.id,
key: :allow_possible_spam,
key: UserCustomAttribute::TRUSTED_BY,
value: 'not important'
}]
)
end
it 'updates the custom attributes', :aggregate_failures do
expect(user.custom_attributes.by_key(UserCustomAttribute::ALLOW_POSSIBLE_SPAM)).to be_present
expect(user.trusted_with_spam_attribute).to be_present
operation
user.reload
expect(user.custom_attributes).to be_empty
expect(user.trusted_with_spam_attribute).to be nil
end
end
end

View File

@ -1,6 +1,6 @@
module gitlab.com/gitlab-org/gitlab/workhorse
go 1.18
go 1.19
require (
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0