Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
7129754815
commit
6e8929e31d
|
|
@ -1 +1 @@
|
|||
fd923fb927c727b14365468890dfc41a53794682
|
||||
f5b045d8694528efbe2e08984ac5867bdfe41aee
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ module Packages
|
|||
end
|
||||
end
|
||||
|
||||
def can_create_package?
|
||||
can?(current_user, :create_package, project)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def package_attrs(attrs)
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@ module Packages
|
|||
include ::Gitlab::Utils::StrongMemoize
|
||||
|
||||
ERROR_REASON_INVALID_PARAMETER = :invalid_parameter
|
||||
ERROR_REASON_PACKAGE_PROTECTED = :package_protected
|
||||
ERROR_RESPONSE_PACKAGE_PROTECTED =
|
||||
ServiceResponse.error(message: 'Package protected.', reason: :package_protected)
|
||||
ERROR_RESPONSE_UNAUTHORIZED = ServiceResponse.error(message: 'Unauthorized', reason: :unauthorized)
|
||||
|
||||
def execute
|
||||
if current_package_protected?
|
||||
return ServiceResponse.error(message: 'Package protected.',
|
||||
reason: ERROR_REASON_PACKAGE_PROTECTED)
|
||||
end
|
||||
return ERROR_RESPONSE_UNAUTHORIZED unless can_create_package?
|
||||
return ERROR_RESPONSE_PACKAGE_PROTECTED if current_package_protected?
|
||||
|
||||
::Packages::Package.transaction do
|
||||
meta = Packages::Pypi::Metadatum.new(
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ migration_job_name: BackfillIncidentManagementPendingAlertEscalationsProjectId
|
|||
description: Backfills sharding key `incident_management_pending_alert_escalations.project_id` from `alert_management_alerts`.
|
||||
feature_category: incident_management
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/166816
|
||||
milestone: '17.5'
|
||||
queued_migration_version: 20240922141648
|
||||
finalize_after: '2024-10-22'
|
||||
milestone: '17.6'
|
||||
queued_migration_version: 20241025073808
|
||||
finalized_by: # version of the migration that finalized this BBM
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddCreatedByToCustomFields < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.6'
|
||||
|
||||
def change
|
||||
add_reference :custom_fields, :created_by, index: true, foreign_key: { on_delete: :nullify, to_table: :users } # rubocop:disable Migration/AddReference -- table is empty
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddUpdatedByToCustomFields < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.6'
|
||||
|
||||
def change
|
||||
add_reference :custom_fields, :updated_by, index: true, foreign_key: { on_delete: :nullify, to_table: :users } # rubocop:disable Migration/AddReference -- table is empty
|
||||
end
|
||||
end
|
||||
|
|
@ -7,13 +7,12 @@ class AddIncidentManagementPendingAlertEscalationsProjectIdFk < Gitlab::Database
|
|||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_partitioned_foreign_key :incident_management_pending_alert_escalations, :projects,
|
||||
column: :project_id, on_delete: :cascade
|
||||
# no-op because there was a bug in the original migration, which has been
|
||||
# fixed by https://gitlab.com/gitlab-org/gitlab/-/merge_requests/168212
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_foreign_key :incident_management_pending_alert_escalations, column: :project_id
|
||||
end
|
||||
# no-op because there was a bug in the original migration, which has been
|
||||
# fixed by https://gitlab.com/gitlab-org/gitlab/-/merge_requests/168212
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,22 +4,12 @@ class AddIncidentManagementPendingAlertEscalationsProjectIdTrigger < Gitlab::Dat
|
|||
milestone '17.5'
|
||||
|
||||
def up
|
||||
install_sharding_key_assignment_trigger(
|
||||
table: :incident_management_pending_alert_escalations,
|
||||
sharding_key: :project_id,
|
||||
parent_table: :alert_management_alerts,
|
||||
parent_sharding_key: :project_id,
|
||||
foreign_key: :alert_id
|
||||
)
|
||||
# no-op because there was a bug in the original migration, which has been
|
||||
# fixed by https://gitlab.com/gitlab-org/gitlab/-/merge_requests/168212
|
||||
end
|
||||
|
||||
def down
|
||||
remove_sharding_key_assignment_trigger(
|
||||
table: :incident_management_pending_alert_escalations,
|
||||
sharding_key: :project_id,
|
||||
parent_table: :alert_management_alerts,
|
||||
parent_sharding_key: :project_id,
|
||||
foreign_key: :alert_id
|
||||
)
|
||||
# no-op because there was a bug in the original migration, which has been
|
||||
# fixed by https://gitlab.com/gitlab-org/gitlab/-/merge_requests/168212
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,32 +10,12 @@ class QueueBackfillIncidentManagementPendingAlertEscalationsProjectId < Gitlab::
|
|||
SUB_BATCH_SIZE = 100
|
||||
|
||||
def up
|
||||
queue_batched_background_migration(
|
||||
MIGRATION,
|
||||
:incident_management_pending_alert_escalations,
|
||||
:id,
|
||||
:project_id,
|
||||
:alert_management_alerts,
|
||||
:project_id,
|
||||
:alert_id,
|
||||
job_interval: DELAY_INTERVAL,
|
||||
batch_size: BATCH_SIZE,
|
||||
batch_class_name: 'LooseIndexScanBatchingStrategy',
|
||||
sub_batch_size: SUB_BATCH_SIZE
|
||||
)
|
||||
# no-op because there was a bug in the original migration, which has been
|
||||
# fixed by https://gitlab.com/gitlab-org/gitlab/-/merge_requests/168212
|
||||
end
|
||||
|
||||
def down
|
||||
delete_batched_background_migration(
|
||||
MIGRATION,
|
||||
:incident_management_pending_alert_escalations,
|
||||
:id,
|
||||
[
|
||||
:project_id,
|
||||
:alert_management_alerts,
|
||||
:project_id,
|
||||
:alert_id
|
||||
]
|
||||
)
|
||||
# no-op because there was a bug in the original migration, which has been
|
||||
# fixed by https://gitlab.com/gitlab-org/gitlab/-/merge_requests/168212
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemoveBbmIncidentManagementPendingAlertEscProjectId < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.6'
|
||||
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main_cell
|
||||
|
||||
MIGRATION = "BackfillIncidentManagementPendingAlertEscalationsProjectId"
|
||||
|
||||
def up
|
||||
delete_batched_background_migration(MIGRATION, :incident_management_pending_alert_escalations, :id,
|
||||
[:project_id, :alert_management_alerts, :project_id, :alert_id])
|
||||
end
|
||||
|
||||
def down; end
|
||||
end
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemoveIncidentManagementPendingAlertEscProjectIdFk < Gitlab::Database::Migration[2.2]
|
||||
include Gitlab::Database::PartitioningMigrationHelpers
|
||||
|
||||
milestone '17.6'
|
||||
disable_ddl_transaction!
|
||||
|
||||
CONSTRAINT_NAME = 'fk_rails_2bbafb00ef'
|
||||
|
||||
def up
|
||||
with_lock_retries do
|
||||
remove_foreign_key_if_exists(:incident_management_pending_alert_escalations, :projects, name: CONSTRAINT_NAME)
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
add_concurrent_partitioned_foreign_key :incident_management_pending_alert_escalations, :projects,
|
||||
column: :project_id, on_delete: :cascade, name: CONSTRAINT_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemoveIncidentManagementPendingAlertEscProjectIdTrigger < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.6'
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
with_lock_retries do
|
||||
execute <<~SQL
|
||||
DROP TRIGGER IF EXISTS trigger_2a994bb5629f ON incident_management_pending_alert_escalations;
|
||||
DROP FUNCTION IF EXISTS trigger_2a994bb5629f();
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
execute <<~SQL
|
||||
CREATE FUNCTION trigger_2a994bb5629f() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
IF NEW."project_id" IS NULL THEN
|
||||
SELECT "project_id"
|
||||
INTO NEW."project_id"
|
||||
FROM "alert_management_alerts"
|
||||
WHERE "alert_management_alerts"."id" = NEW."alert_id";
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
|
||||
CREATE TRIGGER trigger_2a994bb5629f
|
||||
BEFORE INSERT OR UPDATE ON incident_management_pending_alert_escalations
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION trigger_2a994bb5629f();
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddIncidentManagementPendingAlertEscProjectIdFk < Gitlab::Database::Migration[2.2]
|
||||
include Gitlab::Database::PartitioningMigrationHelpers
|
||||
|
||||
milestone '17.6'
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_partitioned_foreign_key :incident_management_pending_alert_escalations, :projects,
|
||||
column: :project_id, on_delete: :cascade, reverse_lock_order: true
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_foreign_key_if_exists :incident_management_pending_alert_escalations, column: :project_id,
|
||||
reverse_lock_order: true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddIncidentManagementPendingAlertEscProjectIdTrigger < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.6'
|
||||
|
||||
def up
|
||||
install_sharding_key_assignment_trigger(
|
||||
table: :incident_management_pending_alert_escalations,
|
||||
sharding_key: :project_id,
|
||||
parent_table: :alert_management_alerts,
|
||||
parent_sharding_key: :project_id,
|
||||
foreign_key: :alert_id
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
remove_sharding_key_assignment_trigger(
|
||||
table: :incident_management_pending_alert_escalations,
|
||||
sharding_key: :project_id,
|
||||
parent_table: :alert_management_alerts,
|
||||
parent_sharding_key: :project_id,
|
||||
foreign_key: :alert_id
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class QueueBackfillIncidentManagementPendingAlertEscProjectId < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.6'
|
||||
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main_cell
|
||||
|
||||
MIGRATION = "BackfillIncidentManagementPendingAlertEscalationsProjectId"
|
||||
DELAY_INTERVAL = 2.minutes
|
||||
BATCH_SIZE = 1000
|
||||
SUB_BATCH_SIZE = 100
|
||||
|
||||
def up
|
||||
queue_batched_background_migration(
|
||||
MIGRATION,
|
||||
:incident_management_pending_alert_escalations,
|
||||
:id,
|
||||
:project_id,
|
||||
:alert_management_alerts,
|
||||
:project_id,
|
||||
:alert_id,
|
||||
job_interval: DELAY_INTERVAL,
|
||||
batch_size: BATCH_SIZE,
|
||||
batch_class_name: 'LooseIndexScanBatchingStrategy',
|
||||
sub_batch_size: SUB_BATCH_SIZE
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
delete_batched_background_migration(
|
||||
MIGRATION,
|
||||
:incident_management_pending_alert_escalations,
|
||||
:id,
|
||||
[
|
||||
:project_id,
|
||||
:alert_management_alerts,
|
||||
:project_id,
|
||||
:alert_id
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
a0e4e34019e63322618d0bad2a1c271f07dfb99852ef913045e35bbba7f2a6a1
|
||||
|
|
@ -0,0 +1 @@
|
|||
0f9f28442fc0a89d1beb1f89b17df636a409e6841f9ab234dc8297a6fb4625aa
|
||||
|
|
@ -0,0 +1 @@
|
|||
d9f0d28c35d08427014710004597625e351f8c8ad9fb2e244887c9201e0177ea
|
||||
|
|
@ -0,0 +1 @@
|
|||
d30a5ae139557ab677d23941ce5b55ecb0f6d67f7b55035ea33fb229eb236cc6
|
||||
|
|
@ -0,0 +1 @@
|
|||
345f6b90e74d6c7a5e6133d4f895717f76aa4156ac877cd494c5e16c320a053a
|
||||
|
|
@ -0,0 +1 @@
|
|||
0f7f885d6493a5c9b6a13641d5e516190511a077f0b91f4d7f2e0cdf4c99e135
|
||||
|
|
@ -0,0 +1 @@
|
|||
55055788e7c493b41c9d18f5cb03dacd157827cd92d31dd40d4790e2b3a6373d
|
||||
|
|
@ -0,0 +1 @@
|
|||
c4a17ceba5f4174bd71068b5ff12d2f38b1c744e6304cbdd635320929fbb868b
|
||||
|
|
@ -10162,6 +10162,8 @@ CREATE TABLE custom_fields (
|
|||
archived_at timestamp with time zone,
|
||||
field_type smallint NOT NULL,
|
||||
name text NOT NULL,
|
||||
created_by_id bigint,
|
||||
updated_by_id bigint,
|
||||
CONSTRAINT check_b047b04af9 CHECK ((char_length(name) <= 255))
|
||||
);
|
||||
|
||||
|
|
@ -28765,6 +28767,10 @@ CREATE UNIQUE INDEX index_custom_emoji_on_namespace_id_and_name ON custom_emoji
|
|||
|
||||
CREATE INDEX index_custom_field_select_options_on_namespace_id ON custom_field_select_options USING btree (namespace_id);
|
||||
|
||||
CREATE INDEX index_custom_fields_on_created_by_id ON custom_fields USING btree (created_by_id);
|
||||
|
||||
CREATE INDEX index_custom_fields_on_updated_by_id ON custom_fields USING btree (updated_by_id);
|
||||
|
||||
CREATE UNIQUE INDEX index_custom_software_licenses_on_project_id_and_name ON custom_software_licenses USING btree (project_id, name);
|
||||
|
||||
CREATE INDEX index_customer_relations_contacts_on_group_id ON customer_relations_contacts USING btree (group_id);
|
||||
|
|
@ -36232,6 +36238,9 @@ ALTER TABLE ONLY ci_builds
|
|||
ALTER TABLE ONLY upcoming_reconciliations
|
||||
ADD CONSTRAINT fk_rails_497b4938ac FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY custom_fields
|
||||
ADD CONSTRAINT fk_rails_4a74c8558e FOREIGN KEY (created_by_id) REFERENCES users(id) ON DELETE SET NULL;
|
||||
|
||||
ALTER TABLE ONLY group_deletion_schedules
|
||||
ADD CONSTRAINT fk_rails_4b8c694a6c FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
|
||||
|
||||
|
|
@ -36628,6 +36637,9 @@ ALTER TABLE ONLY dependency_proxy_manifest_states
|
|||
ALTER TABLE ONLY ci_job_artifact_states
|
||||
ADD CONSTRAINT fk_rails_80a9cba3b2_p FOREIGN KEY (partition_id, job_artifact_id) REFERENCES p_ci_job_artifacts(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY custom_fields
|
||||
ADD CONSTRAINT fk_rails_80c4a47616 FOREIGN KEY (updated_by_id) REFERENCES users(id) ON DELETE SET NULL;
|
||||
|
||||
ALTER TABLE ONLY approval_merge_request_rules_users
|
||||
ADD CONSTRAINT fk_rails_80e6801803 FOREIGN KEY (approval_merge_request_rule_id) REFERENCES approval_merge_request_rules(id) ON DELETE CASCADE;
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ for all authenticated users, and on the **Admin** area pages. The statuses are:
|
|||
- Red: The version of GitLab you are running is vulnerable. You should install
|
||||
the latest version with security fixes as soon as possible.
|
||||
|
||||

|
||||

|
||||
|
||||
### Enable or disable version check
|
||||
|
||||
|
|
|
|||
|
|
@ -3880,6 +3880,55 @@ Input type: `CreateTestCaseInput`
|
|||
| <a id="mutationcreatetestcaseerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||
| <a id="mutationcreatetestcasetestcase"></a>`testCase` | [`Issue`](#issue) | Test case created. |
|
||||
|
||||
### `Mutation.customFieldCreate`
|
||||
|
||||
DETAILS:
|
||||
**Introduced** in GitLab 17.6.
|
||||
**Status**: Experiment.
|
||||
|
||||
Input type: `CustomFieldCreateInput`
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationcustomfieldcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationcustomfieldcreatefieldtype"></a>`fieldType` | [`CustomFieldType!`](#customfieldtype) | Type of custom field. |
|
||||
| <a id="mutationcustomfieldcreategrouppath"></a>`groupPath` | [`ID!`](#id) | Group path where the custom field is created. |
|
||||
| <a id="mutationcustomfieldcreatename"></a>`name` | [`String!`](#string) | Name of the custom field. |
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationcustomfieldcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationcustomfieldcreatecustomfield"></a>`customField` | [`CustomField`](#customfield) | Created custom field. |
|
||||
| <a id="mutationcustomfieldcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||
|
||||
### `Mutation.customFieldUpdate`
|
||||
|
||||
DETAILS:
|
||||
**Introduced** in GitLab 17.6.
|
||||
**Status**: Experiment.
|
||||
|
||||
Input type: `CustomFieldUpdateInput`
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationcustomfieldupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationcustomfieldupdateid"></a>`id` | [`IssuablesCustomFieldID!`](#issuablescustomfieldid) | Global ID of the custom field. |
|
||||
| <a id="mutationcustomfieldupdatename"></a>`name` | [`String!`](#string) | Name of the custom field. |
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationcustomfieldupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationcustomfieldupdatecustomfield"></a>`customField` | [`CustomField`](#customfield) | Updated custom field. |
|
||||
| <a id="mutationcustomfieldupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||
|
||||
### `Mutation.customerRelationsContactCreate`
|
||||
|
||||
Input type: `CustomerRelationsContactCreateInput`
|
||||
|
|
@ -21420,11 +21469,13 @@ Represents a custom field.
|
|||
| ---- | ---- | ----------- |
|
||||
| <a id="customfieldactive"></a>`active` | [`Boolean!`](#boolean) | Whether the custom field is active. |
|
||||
| <a id="customfieldcreatedat"></a>`createdAt` | [`Time!`](#time) | Timestamp when the custom field was created. |
|
||||
| <a id="customfieldcreatedby"></a>`createdBy` | [`UserCore`](#usercore) | User that created the custom field. |
|
||||
| <a id="customfieldfieldtype"></a>`fieldType` | [`CustomFieldType!`](#customfieldtype) | Type of custom field. |
|
||||
| <a id="customfieldid"></a>`id` | [`IssuablesCustomFieldID!`](#issuablescustomfieldid) | Global ID of the custom field. |
|
||||
| <a id="customfieldname"></a>`name` | [`String!`](#string) | Name of the custom field. |
|
||||
| <a id="customfieldselectoptions"></a>`selectOptions` | [`[CustomFieldSelectOption!]`](#customfieldselectoption) | Available options for a select field. |
|
||||
| <a id="customfieldupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp when the custom field was last updated. |
|
||||
| <a id="customfieldupdatedby"></a>`updatedBy` | [`UserCore`](#usercore) | User that last updated the custom field. |
|
||||
| <a id="customfieldworkitemtypes"></a>`workItemTypes` | [`[WorkItemType!]`](#workitemtype) | Work item types that the custom field is available on. |
|
||||
|
||||
### `CustomFieldSelectOption`
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ The first step is to benchmark the cadence of code releases between groups and p
|
|||
|
||||
Lead time for changes is the amount of time it takes a code change to get into production.
|
||||
|
||||
**Lead time for changes** is not the same as **Lead time**. In the value stream, lead time measures the time it takes for work on an issue to move from the moment it's requested (Issue created) to the moment it's fulfilled and delivered (Issue closed).
|
||||
**Lead time for changes** is not the same as **Lead time**. In value stream analytics, lead time measures the time it takes for work on an issue to move from the moment it's requested (Issue created) to the moment it's fulfilled and delivered (Issue closed).
|
||||
|
||||
For software leaders, lead time for changes reflects the efficiency of CI/CD pipelines and visualizes how quickly work is delivered to customers.
|
||||
Over time, the lead time for changes should decrease, while your team's performance should increase. Low lead time for changes means more efficient CI/CD pipelines.
|
||||
|
|
@ -94,6 +94,7 @@ The first step is to benchmark the CI/CD pipelines' efficiency between groups an
|
|||
- Using Value Stream Analytics to identify bottlenecks in the processes.
|
||||
- Breaking the changes down into smaller iterations.
|
||||
- Adding automation.
|
||||
- Improving the performance of your pipelines.
|
||||
|
||||
## Time to restore service
|
||||
|
||||
|
|
@ -104,7 +105,7 @@ Low time to restore service means the organization can take risks with new innov
|
|||
|
||||
### How time to restore service is calculated
|
||||
|
||||
In GitLab, time to restore service is measured as the median time an incident was open for on a production environment.
|
||||
In GitLab, time to restore service is measured as the median time an incident was open on a production environment.
|
||||
GitLab calculates the number of seconds an incident was open on a production environment in the given time period. This assumes:
|
||||
|
||||
- [GitLab incidents](../../operations/incident_management/incidents.md) are tracked.
|
||||
|
|
@ -117,17 +118,18 @@ The first step is to benchmark the team response and recover from service interr
|
|||
|
||||
- Improving the observability into the production environment.
|
||||
- Improving response workflows.
|
||||
- Improving deployment frequency and lead time for changes so fixes can get into production more efficiently.
|
||||
|
||||
## Change failure rate
|
||||
|
||||
Change failure rate is how often a change cause failure in production.
|
||||
Change failure rate is how often a change causes a failure in production.
|
||||
|
||||
Software leaders can use the change failure rate metric to gain insights into the quality of the code being shipped.
|
||||
High change failure rate may indicate an inefficient deployment process or insufficient automated testing coverage.
|
||||
|
||||
### How change failure rate is calculated
|
||||
|
||||
In GitLab, change failure rate is measured as the percentage of deployments that cause an incident in production in the given time period.
|
||||
In GitLab, change failure rate is measured as the percentage of deployments that cause an incident in production in a given time period.
|
||||
GitLab calculates change failure rate as the number of incidents divided by the number of deployments to a production environment. This calculation assumes:
|
||||
|
||||
- [GitLab incidents](../../operations/incident_management/incidents.md) are tracked.
|
||||
|
|
@ -227,7 +229,7 @@ These deployment records are not created for pull-based deployments, for example
|
|||
|
||||
To track DORA metrics in these cases, you can [create a deployment record](../../api/deployments.md#create-a-deployment) using the Deployments API.
|
||||
You must set the environment name where the deployment tier is configured, because the tier variable is specified for the given environment, not for the deployments.
|
||||
For more information, see [Track deployments of an external deployment tool](../../ci/environments/external_deployment_tools.md).
|
||||
For more information, see [track deployments of an external deployment tool](../../ci/environments/external_deployment_tools.md).
|
||||
|
||||
### Measure DORA metrics with Jira
|
||||
|
||||
|
|
@ -239,7 +241,7 @@ For more information, see [Track deployments of an external deployment tool](../
|
|||
For PagerDuty, you can set up a [webhook to automatically create a GitLab incident for each PagerDuty incident](../../operations/incident_management/manage_incidents.md#using-the-pagerduty-webhook).
|
||||
This configuration requires you to make changes in both PagerDuty and GitLab.
|
||||
|
||||
For others incident management tools, you can set up the
|
||||
For other incident management tools, you can set up the
|
||||
[HTTP integration](../../operations/incident_management/integrations.md#http-endpoints),
|
||||
and use it to automatically:
|
||||
|
||||
|
|
@ -252,8 +254,8 @@ The table below provides an overview of the DORA metrics' availability in projec
|
|||
|
||||
| Metric | Level | Comments |
|
||||
|---------------------------|-------------------|----------|
|
||||
| `deployment_frequency` | Project | |
|
||||
| `deployment_frequency` | Group | |
|
||||
| `deployment_frequency` | Project | Unit in deployment count. |
|
||||
| `deployment_frequency` | Group | Unit in deployment count. Aggregation method is average. |
|
||||
| `lead_time_for_changes` | Project | Unit in seconds. Aggregation method is median. |
|
||||
| `lead_time_for_changes` | Group | Unit in seconds. Aggregation method is median. |
|
||||
| `time_to_restore_service` | Project and group | Unit in days. Aggregation method is median. (Available in UI chart in GitLab 15.1 and later) |
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ To view contribution analytics:
|
|||
Three bar charts and a table illustrate the number of contributions made by each group member:
|
||||
|
||||
- Push events
|
||||
- Merge requests
|
||||
- Closed issues
|
||||
- Created, merged, and closed merge requests
|
||||
- Created and closed issues
|
||||
|
||||
### View a member's contributions
|
||||
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ module API
|
|||
.new(project, current_user, declared_params.merge(build: current_authenticated_job))
|
||||
.execute
|
||||
|
||||
if service_response.error? && service_response.reason == Packages::Pypi::CreatePackageService::ERROR_REASON_PACKAGE_PROTECTED
|
||||
if service_response.error? && service_response.reason == Packages::Pypi::CreatePackageService::ERROR_RESPONSE_PACKAGE_PROTECTED.reason
|
||||
forbidden!(service_response.message)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -64535,6 +64535,9 @@ msgstr ""
|
|||
msgid "can only be changed by a group admin."
|
||||
msgstr ""
|
||||
|
||||
msgid "can only have a maximum of %{limit} active custom fields."
|
||||
msgstr ""
|
||||
|
||||
msgid "can only have one escalation policy"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
require 'spec_helper'
|
||||
require_migration!
|
||||
|
||||
RSpec.describe QueueBackfillIncidentManagementPendingAlertEscalationsProjectId, feature_category: :incident_management do
|
||||
RSpec.describe QueueBackfillIncidentManagementPendingAlertEscProjectId, feature_category: :incident_management do
|
||||
let!(:batched_migration) { described_class::MIGRATION }
|
||||
|
||||
it 'schedules a new batched migration' do
|
||||
|
|
@ -24,9 +24,21 @@ RSpec.describe Packages::Pypi::CreatePackageService, :aggregate_failures, featur
|
|||
}
|
||||
end
|
||||
|
||||
describe '#execute' do
|
||||
subject(:execute_service) { described_class.new(project, user, params).execute }
|
||||
subject(:execute_service) { described_class.new(project, user, params).execute }
|
||||
|
||||
shared_examples 'an error response while not creating a pypi package' do |message:, reason:|
|
||||
it_behaves_like 'returning an error service response', message: message
|
||||
it { is_expected.to have_attributes(reason: reason) }
|
||||
|
||||
it 'does not create any pypi-related package records' do
|
||||
expect { execute_service }
|
||||
.to not_change { Packages::Package.count }
|
||||
.and not_change { Packages::Package.pypi.count }
|
||||
.and not_change { Packages::PackageFile.count }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#execute' do
|
||||
let(:created_package) { Packages::Package.pypi.last }
|
||||
|
||||
context 'without an existing package' do
|
||||
|
|
@ -150,16 +162,9 @@ RSpec.describe Packages::Pypi::CreatePackageService, :aggregate_failures, featur
|
|||
params[:md5_digest] = md5
|
||||
end
|
||||
|
||||
it_behaves_like 'returning an error service response',
|
||||
message: 'Validation failed: File name has already been taken' do
|
||||
it { is_expected.to have_attributes(reason: :invalid_parameter) }
|
||||
end
|
||||
|
||||
it 'does not create a pypi package' do
|
||||
expect { execute_service }
|
||||
.to change { Packages::Package.pypi.count }.by(0)
|
||||
.and change { Packages::PackageFile.count }.by(0)
|
||||
end
|
||||
it_behaves_like 'an error response while not creating a pypi package',
|
||||
message: 'Validation failed: File name has already been taken',
|
||||
reason: :invalid_parameter
|
||||
|
||||
context 'with a pending_destruction package' do
|
||||
before do
|
||||
|
|
@ -199,6 +204,22 @@ RSpec.describe Packages::Pypi::CreatePackageService, :aggregate_failures, featur
|
|||
end
|
||||
end
|
||||
|
||||
context 'with unauthorized user' do
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
it_behaves_like 'an error response while not creating a pypi package',
|
||||
message: 'Unauthorized',
|
||||
reason: :unauthorized
|
||||
end
|
||||
|
||||
context 'without user' do
|
||||
let_it_be(:user) { nil }
|
||||
|
||||
it_behaves_like 'an error response while not creating a pypi package',
|
||||
message: 'Unauthorized',
|
||||
reason: :unauthorized
|
||||
end
|
||||
|
||||
context 'with package protection rule for different roles and package_name_patterns' do
|
||||
let_it_be_with_reload(:package_protection_rule) do
|
||||
create(:package_protection_rule, package_type: :pypi, project: project)
|
||||
|
|
@ -245,8 +266,9 @@ RSpec.describe Packages::Pypi::CreatePackageService, :aggregate_failures, featur
|
|||
end
|
||||
|
||||
shared_examples 'an error service response for unauthorized' do
|
||||
it_behaves_like 'returning an error service response', message: 'Unauthorized'
|
||||
it { is_expected.to have_attributes(reason: :invalid_parameter) }
|
||||
it_behaves_like 'an error response while not creating a pypi package',
|
||||
message: 'Unauthorized',
|
||||
reason: :unauthorized
|
||||
end
|
||||
|
||||
before do
|
||||
|
|
|
|||
Loading…
Reference in New Issue