Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-08-30 15:10:02 +00:00
parent 60273ebb30
commit 4b1fc3dc32
57 changed files with 998 additions and 391 deletions

View File

@ -931,6 +931,14 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/app/models/token_with_iv.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/models/webauthn_registration.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/policies/personal_access_token_policy.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/serializers/group_access_token_entity.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/serializers/group_access_token_serializer.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/serializers/impersonation_access_token_entity.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/serializers/impersonation_access_token_serializer.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/serializers/personal_access_token_entity.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/serializers/personal_access_token_serializer.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/serializers/project_access_token_entity.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/serializers/project_access_token_serializer.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/services/access_token_validation_service.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/services/auth/ @gitlab-org/manage/authentication-and-authorization/approvers
/app/services/authorized_project_update/ @gitlab-org/manage/authentication-and-authorization/approvers
@ -941,8 +949,11 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/app/services/todos/destroy/unauthorized_features_service.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/services/users/authorized_build_service.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/services/users/authorized_create_service.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/services/users/email_verification/generate_token_service.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/services/users/email_verification/validate_token_service.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/services/users/refresh_authorized_projects_service.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/services/webauthn/ @gitlab-org/manage/authentication-and-authorization/approvers
/app/validators/json_schemas/build_metadata_id_tokens.json @gitlab-org/manage/authentication-and-authorization/approvers
/app/validators/json_schemas/cluster_agent_authorization_configuration.json @gitlab-org/manage/authentication-and-authorization/approvers
/app/views/admin/application_settings/_external_authorization_service_form.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
/app/views/admin/impersonation_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
@ -987,20 +998,6 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/app/workers/authorized_project_update/ @gitlab-org/manage/authentication-and-authorization/approvers
/app/workers/authorized_projects_worker.rb @gitlab-org/manage/authentication-and-authorization/approvers
/app/workers/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
/config/feature_flags/development/access_token_pagination.yml @gitlab-org/manage/authentication-and-authorization/approvers
/config/feature_flags/development/application_settings_tokens_optional_encryption.yml @gitlab-org/manage/authentication-and-authorization/approvers
/config/feature_flags/development/enforce_auth_checks_on_uploads.yml @gitlab-org/manage/authentication-and-authorization/approvers
/config/feature_flags/development/forti_authenticator.yml @gitlab-org/manage/authentication-and-authorization/approvers
/config/feature_flags/development/forti_token_cloud.yml @gitlab-org/manage/authentication-and-authorization/approvers
/config/feature_flags/development/groups_tokens_optional_encryption.yml @gitlab-org/manage/authentication-and-authorization/approvers
/config/feature_flags/development/pbkdf2_password_encryption.yml @gitlab-org/manage/authentication-and-authorization/approvers
/config/feature_flags/development/pbkdf2_password_encryption_write.yml @gitlab-org/manage/authentication-and-authorization/approvers
/config/feature_flags/development/projects_tokens_optional_encryption.yml @gitlab-org/manage/authentication-and-authorization/approvers
/config/feature_flags/development/skip_group_share_unlink_auth_refresh.yml @gitlab-org/manage/authentication-and-authorization/approvers
/config/feature_flags/development/specialized_worker_for_group_lock_update_auth_recalculation.yml @gitlab-org/manage/authentication-and-authorization/approvers
/config/feature_flags/development/update_oauth_registration_flow.yml @gitlab-org/manage/authentication-and-authorization/approvers
/config/feature_flags/development/webauthn.yml @gitlab-org/manage/authentication-and-authorization/approvers
/config/feature_flags/ops/block_password_auth_for_saml_users.yml @gitlab-org/manage/authentication-and-authorization/approvers
/config/initializers/01_secret_token.rb @gitlab-org/manage/authentication-and-authorization/approvers
/config/initializers/devise_dynamic_password_length_validation.rb @gitlab-org/manage/authentication-and-authorization/approvers
/config/initializers/devise_password_length.rb.example @gitlab-org/manage/authentication-and-authorization/approvers
@ -1014,6 +1011,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/ee/app/assets/javascripts/access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
/ee/app/assets/javascripts/audit_events/components/tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
/ee/app/assets/javascripts/audit_events/token_utils.js @gitlab-org/manage/authentication-and-authorization/approvers
/ee/app/assets/javascripts/batch_comments/ @gitlab-org/manage/authentication-and-authorization/approvers
/ee/app/assets/javascripts/groups/settings/components/ @gitlab-org/manage/authentication-and-authorization/approvers
/ee/app/assets/javascripts/pages/admin/application_settings/general/components/ @gitlab-org/manage/authentication-and-authorization/approvers
/ee/app/assets/javascripts/pages/groups/omniauth_callbacks/ @gitlab-org/manage/authentication-and-authorization/approvers
@ -1101,6 +1099,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/lib/gitlab/background_migration/update_users_where_two_factor_auth_required_from_group.rb @gitlab-org/manage/authentication-and-authorization/approvers
/lib/gitlab/chat_name_token.rb @gitlab-org/manage/authentication-and-authorization/approvers
/lib/gitlab/ci/pipeline/expression/token.rb @gitlab-org/manage/authentication-and-authorization/approvers
/lib/gitlab/cleanup/unused_personal_access_tokens.rb @gitlab-org/manage/authentication-and-authorization/approvers
/lib/gitlab/external_authorization/ @gitlab-org/manage/authentication-and-authorization/approvers
/lib/gitlab/external_authorization.rb @gitlab-org/manage/authentication-and-authorization/approvers
/lib/gitlab/grape_logging/loggers/token_logger.rb @gitlab-org/manage/authentication-and-authorization/approvers
@ -1125,21 +1124,6 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/app/services/audit_event_service.rb @gitlab-org/manage/compliance
/app/services/concerns/audit_event_save_type.rb @gitlab-org/manage/compliance
/app/views/profiles/audit_log.html.haml @gitlab-org/manage/compliance
/data/deprecations/14-3-repository-push-audit-events.yml @gitlab-org/manage/compliance
/data/removals/15_0/removal_manage_repository_push_audit_event.yml @gitlab-org/manage/compliance
/db/docs/audit_events.yml @gitlab-org/manage/compliance
/db/docs/audit_events_external_audit_event_destinations.yml @gitlab-org/manage/compliance
/db/docs/audit_events_streaming_headers.yml @gitlab-org/manage/compliance
/db/migrate/20210819185500_create_external_audit_event_destinations_table.rb @gitlab-org/manage/compliance
/db/migrate/20220524141800_create_audit_events_streaming_headers.rb @gitlab-org/manage/compliance
/db/post_migrate/20210331105335_drop_non_partitioned_audit_events.rb @gitlab-org/manage/compliance
/db/post_migrate/20220119094503_populate_audit_event_streaming_verification_token.rb @gitlab-org/manage/compliance
/doc/administration/audit_event_streaming.md @gitlab-org/manage/compliance
/doc/administration/audit_events.md @gitlab-org/manage/compliance
/doc/administration/audit_reports.md @gitlab-org/manage/compliance
/doc/administration/auditor_users.md @gitlab-org/manage/compliance
/doc/api/audit_events.md @gitlab-org/manage/compliance
/doc/api/graphql/audit_report.md @gitlab-org/manage/compliance
/ee/app/assets/javascripts/audit_events/components/audit_events_app.vue @gitlab-org/manage/compliance
/ee/app/assets/javascripts/audit_events/components/audit_events_export_button.vue @gitlab-org/manage/compliance
/ee/app/assets/javascripts/audit_events/components/audit_events_filter.vue @gitlab-org/manage/compliance
@ -1197,58 +1181,5 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/ee/lib/ee/api/entities/audit_event.rb @gitlab-org/manage/compliance
/ee/lib/ee/audit/ @gitlab-org/manage/compliance
/ee/lib/ee/gitlab/audit/ @gitlab-org/manage/compliance
/ee/spec/controllers/admin/audit_log_reports_controller_spec.rb @gitlab-org/manage/compliance
/ee/spec/controllers/admin/audit_logs_controller_spec.rb @gitlab-org/manage/compliance
/ee/spec/controllers/groups/audit_events_controller_spec.rb @gitlab-org/manage/compliance
/ee/spec/controllers/projects/audit_events_controller_spec.rb @gitlab-org/manage/compliance
/ee/spec/factories/audit_events/external_audit_event_destinations.rb @gitlab-org/manage/compliance
/ee/spec/features/admin/admin_audit_logs_spec.rb @gitlab-org/manage/compliance
/ee/spec/features/groups/audit_events_spec.rb @gitlab-org/manage/compliance
/ee/spec/features/projects/audit_events_spec.rb @gitlab-org/manage/compliance
/ee/spec/finders/audit_event_finder_spec.rb @gitlab-org/manage/compliance
/ee/spec/fixtures/api/schemas/public_api/v4/audit_event.json @gitlab-org/manage/compliance
/ee/spec/fixtures/api/schemas/public_api/v4/audit_events.json @gitlab-org/manage/compliance
/ee/spec/frontend/audit_events/components/__snapshots__/ @gitlab-org/manage/compliance
/ee/spec/frontend/audit_events/components/audit_events_app_spec.js @gitlab-org/manage/compliance
/ee/spec/frontend/audit_events/components/audit_events_export_button_spec.js @gitlab-org/manage/compliance
/ee/spec/frontend/audit_events/components/audit_events_filter_spec.js @gitlab-org/manage/compliance
/ee/spec/frontend/audit_events/components/audit_events_logs_spec.js @gitlab-org/manage/compliance
/ee/spec/frontend/audit_events/components/audit_events_stream_spec.js @gitlab-org/manage/compliance
/ee/spec/frontend/audit_events/components/audit_events_table_spec.js @gitlab-org/manage/compliance
/ee/spec/frontend/audit_events/components/tokens/shared/ @gitlab-org/manage/compliance
/ee/spec/graphql/types/audit_events/exterrnal_audit_event_destination_type_spec.rb @gitlab-org/manage/compliance
/ee/spec/helpers/audit_events_helper_spec.rb @gitlab-org/manage/compliance
/ee/spec/lib/audit/external_status_check_changes_auditor_spec.rb @gitlab-org/manage/compliance
/ee/spec/lib/audit/group_merge_request_approval_setting_changes_auditor_spec.rb @gitlab-org/manage/compliance
/ee/spec/lib/audit/group_push_rules_changes_auditor_spec.rb @gitlab-org/manage/compliance
/ee/spec/lib/ee/audit/ @gitlab-org/manage/compliance
/ee/spec/lib/gitlab/audit/auditor_spec.rb @gitlab-org/manage/compliance
/ee/spec/models/audit_events/external_audit_event_destination_spec.rb @gitlab-org/manage/compliance
/ee/spec/models/concerns/auditable_spec.rb @gitlab-org/manage/compliance
/ee/spec/models/ee/audit_event_spec.rb @gitlab-org/manage/compliance
/ee/spec/presenters/audit_event_presenter_spec.rb @gitlab-org/manage/compliance
/ee/spec/requests/admin/audit_events_spec.rb @gitlab-org/manage/compliance
/ee/spec/requests/api/audit_events_spec.rb @gitlab-org/manage/compliance
/ee/spec/requests/api/graphql/group/external_audit_event_destinations_spec.rb @gitlab-org/manage/compliance
/ee/spec/requests/groups/audit_events_spec.rb @gitlab-org/manage/compliance
/ee/spec/requests/projects/audit_events_spec.rb @gitlab-org/manage/compliance
/ee/spec/serializers/audit_event_entity_spec.rb @gitlab-org/manage/compliance
/ee/spec/serializers/audit_event_serializer_spec.rb @gitlab-org/manage/compliance
/ee/spec/services/audit_event_service_spec.rb @gitlab-org/manage/compliance
/ee/spec/support/shared_contexts/audit_event_not_licensed_shared_context.rb @gitlab-org/manage/compliance
/ee/spec/support/shared_contexts/audit_event_queue_shared_context.rb @gitlab-org/manage/compliance
/ee/spec/support/shared_examples/audit/ @gitlab-org/manage/compliance
/ee/spec/support/shared_examples/features/audit_events_filter_shared_examples.rb @gitlab-org/manage/compliance
/ee/spec/support/shared_examples/services/audit_event_logging_shared_examples.rb @gitlab-org/manage/compliance
/ee/spec/workers/audit_events/audit_event_streaming_worker_spec.rb @gitlab-org/manage/compliance
/lib/gitlab/audit/auditor.rb @gitlab-org/manage/compliance
/lib/gitlab/audit_json_logger.rb @gitlab-org/manage/compliance
/spec/factories/audit_events.rb @gitlab-org/manage/compliance
/spec/lib/gitlab/audit/auditor_spec.rb @gitlab-org/manage/compliance
/spec/migrations/populate_audit_event_streaming_verification_token_spec.rb @gitlab-org/manage/compliance
/spec/models/audit_event_spec.rb @gitlab-org/manage/compliance
/spec/services/audit_event_service_spec.rb @gitlab-org/manage/compliance
/spec/services/concerns/audit_event_save_type_spec.rb @gitlab-org/manage/compliance
/spec/support/shared_examples/sends_git_audit_streaming_event_shared_examples.rb @gitlab-org/manage/compliance
/spec/views/profiles/audit_log.html.haml_spec.rb @gitlab-org/manage/compliance
/vendor/project_templates/hipaa_audit_protocol.tar.gz @gitlab-org/manage/compliance

View File

@ -39,7 +39,7 @@ gem 'ruby-saml', '~> 1.13.0'
gem 'omniauth', '~> 1.8'
gem 'omniauth-auth0', '~> 2.0.0'
gem 'omniauth-azure-activedirectory-v2', '~> 1.0'
gem 'omniauth-azure-oauth2', '~> 0.0.9' # See vendor/gems/omniauth-azure-oauth2/README.md
gem 'omniauth-azure-oauth2', '~> 0.0.9', path: 'vendor/gems/omniauth-azure-oauth2' # See gem README.md
gem 'omniauth-cas3', '~> 1.1.4', path: 'vendor/gems/omniauth-cas3' # See vendor/gems/omniauth-cas3/README.md
gem 'omniauth-dingtalk-oauth2', '~> 1.0'
gem 'omniauth-alicloud', '~> 1.0.1'

View File

@ -24,6 +24,14 @@ PATH
connection_pool (~> 2.0)
mail (~> 2.7)
PATH
remote: vendor/gems/omniauth-azure-oauth2
specs:
omniauth-azure-oauth2 (0.0.10)
jwt (>= 1.0, < 3.0)
omniauth (~> 1.0, < 3)
omniauth-oauth2 (~> 1.4)
PATH
remote: vendor/gems/omniauth-cas3
specs:
@ -910,10 +918,6 @@ GEM
omniauth-oauth2 (>= 1.5)
omniauth-azure-activedirectory-v2 (1.0.0)
omniauth-oauth2 (~> 1.7)
omniauth-azure-oauth2 (0.0.10)
jwt (>= 1.0, < 3.0)
omniauth (~> 1.0)
omniauth-oauth2 (~> 1.4)
omniauth-dingtalk-oauth2 (1.0.1)
omniauth-oauth2 (~> 1.7)
omniauth-facebook (4.0.0)
@ -1663,7 +1667,7 @@ DEPENDENCIES
omniauth-auth0 (~> 2.0.0)
omniauth-authentiq (~> 0.3.3)
omniauth-azure-activedirectory-v2 (~> 1.0)
omniauth-azure-oauth2 (~> 0.0.9)
omniauth-azure-oauth2 (~> 0.0.9)!
omniauth-cas3 (~> 1.1.4)!
omniauth-dingtalk-oauth2 (~> 1.0)
omniauth-facebook (~> 4.0.0)

View File

@ -81,7 +81,12 @@ export default {
this.infoAlert = createAlert({ message: this.alertInfoMessage, variant: VARIANT_INFO });
this.form.reset();
// Reset all input fields except the datepicker.
this.form.querySelectorAll('input:not([id$=expires_at])').forEach((el) => {
// The form token creation is not controlled by Vue.
el.checked = false;
el.value = '';
});
},
},
};

View File

@ -199,7 +199,7 @@ export default {
<div class="gl-display-flex gl-mt-7">
<expiration-dropdown
v-model="prefilledForm.cadence"
:value="prefilledForm.cadence"
:disabled="isFieldDisabled"
:form-options="$options.formOptions.cadence"
:label="$options.i18n.CADENCE_LABEL"
@ -231,7 +231,7 @@ export default {
</gl-sprintf>
</p>
<expiration-dropdown
v-model="prefilledForm.keepN"
:value="prefilledForm.keepN"
:disabled="isFieldDisabled"
:form-options="$options.formOptions.keepN"
:label="$options.i18n.KEEP_N_LABEL"
@ -270,7 +270,7 @@ export default {
</gl-sprintf>
</p>
<expiration-dropdown
v-model="prefilledForm.olderThan"
:value="prefilledForm.olderThan"
:disabled="isFieldDisabled"
:form-options="$options.formOptions.olderThan"
:label="$options.i18n.EXPIRATION_SCHEDULE_LABEL"

View File

@ -4,7 +4,7 @@ module Types
class TimelogType < BaseObject
graphql_name 'Timelog'
authorize :read_issue
authorize :read_issuable
expose_permissions Types::PermissionTypes::Timelog

View File

@ -5,6 +5,7 @@ class IssuablePolicy < BasePolicy
condition(:locked, scope: :subject, score: 0) { @subject.discussion_locked? }
condition(:is_project_member) { @user && @subject.project && @subject.project.team.member?(@user) }
condition(:can_read_issuable) { can?(:"read_#{@subject.to_ability_name}") }
desc "User is the assignee or author"
condition(:assignee_or_author) do
@ -48,6 +49,10 @@ class IssuablePolicy < BasePolicy
rule { can?(:reporter_access) }.policy do
enable :create_timelog
end
rule { can_read_issuable }.policy do
enable :read_issuable
end
end
IssuablePolicy.prepend_mod_with('IssuablePolicy')

View File

@ -23,3 +23,5 @@ class Import::ProviderRepoSerializer < BaseSerializer
super(repo, opts, entity)
end
end
Import::ProviderRepoSerializer.prepend_mod

View File

@ -1,10 +1,9 @@
%p
Hi #{sanitize_name(@user.name)}!
= s_("Notify|Hi %{user}!") % { user: sanitize_name(@user.name) }
%p
A new GPG key was added to your account:
= s_("Notify|A new GPG key was added to your account:")
%p
Fingerprint:
%code= @gpg_key.fingerprint
= s_("Notify|Fingerprint: %{fingerprint}").html_safe % { fingerprint: content_tag(:code, @gpg_key.fingerprint) }
%p
If this key was added in error, you can remove it under
= link_to "GPG Keys", profile_gpg_keys_url
- removal_link = link_to _("GPG Keys"), profile_gpg_keys_url
= s_("Notify|If this key was added in error, you can remove it under %{removal_link}").html_safe % { removal_link: removal_link }

View File

@ -0,0 +1,74 @@
{
"$schema": "http://json-schema.org/draft-06/schema#",
"$id": "https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/audit_events/types/type_schema.json",
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"description": "Unique identifying name for the type of audit event"
},
"description": {
"type": "string",
"description": "A human-readable description of how this event is triggered"
},
"introduced_by_issue": {
"type": "string",
"format": "uri",
"description": "URL to GitLab issue that added this type of audit event",
"qt-uri-protocols": [
"https"
]
},
"introduced_by_mr": {
"type": "string",
"format": "uri",
"description": "URL to GitLab merge request that added this type of audit event",
"qt-uri-protocols": [
"https"
]
},
"group": {
"type": "string",
"description": "Name of the group that introduced this audit event. For example, manage::compliance"
},
"milestone": {
"type": "string",
"description": "Milestone that introduced this audit event type. For example, 15.8",
"pattern": "^[0-9]+\\.[0-9]+$"
},
"saved_to_database": {
"type": "boolean",
"description": "Indicate whether to persist events to database and JSON logs"
},
"streamed": {
"type": "boolean",
"description": "Indicate that events should be streamed to external services (if configured)"
}
},
"required": [
"description",
"group",
"introduced_by_issue",
"introduced_by_mr",
"milestone",
"name",
"saved_to_database",
"streamed"
],
"not": {
"properties": {
"saved_to_database": {
"enum": [
false
]
},
"streamed": {
"enum": [
false
]
}
}
},
"title": "GitLabAuditEventType"
}

View File

@ -0,0 +1,26 @@
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_sast_iac_monthly
description: Count of pipelines with implicit runs using the SAST IaC template
product_section: sec
product_stage: secure
product_group: "static_analysis"
product_category: SAST
value_type: number
status: active
milestone: "15.4"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96120
time_frame: 28d
data_source: redis_hll
data_category: optional
instrumentation_class: RedisHLLMetric
performance_indicator_type: []
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
options:
events:
- p_ci_templates_implicit_jobs_sast_iac

View File

@ -0,0 +1,26 @@
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_sast_iac_monthly
description: Count of pipelines with implicit runs using the SAST IaC template
product_section: sec
product_stage: secure
product_group: "static_analysis"
product_category: SAST
value_type: number
status: active
milestone: "15.4"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96120
time_frame: 28d
data_source: redis_hll
data_category: optional
instrumentation_class: RedisHLLMetric
performance_indicator_type: []
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
options:
events:
- p_ci_templates_implicit_security_sast_iac

View File

@ -0,0 +1,26 @@
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_sast_iac_weekly
description: Count of pipelines with implicit runs using the SAST IaC template
product_section: sec
product_stage: secure
product_group: "static_analysis"
product_category: SAST
value_type: number
status: active
milestone: "15.4"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96120
time_frame: 7d
data_source: redis_hll
data_category: optional
instrumentation_class: RedisHLLMetric
performance_indicator_type: []
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
options:
events:
- p_ci_templates_implicit_jobs_sast_iac

View File

@ -0,0 +1,26 @@
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_sast_iac_weekly
description: Count of pipelines with implicit runs using the SAST IaC template
product_section: sec
product_stage: secure
product_group: "static_analysis"
product_category: SAST
value_type: number
status: active
milestone: "15.4"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96120
time_frame: 7d
data_source: redis_hll
data_category: optional
instrumentation_class: RedisHLLMetric
performance_indicator_type: []
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
options:
events:
- p_ci_templates_implicit_security_sast_iac

View File

@ -10,7 +10,7 @@
gitlab-com: true
available_in: [Free, Premium, Ultimate]
documentation_link: https://docs.gitlab.com/ee/user/tasks.html
image_url: https://about.gitlab.com/images/unreleased/create-tasks.gif
image_url: https://about.gitlab.com/images/15_3/create-tasks.gif
published_at: 2022-08-22
release: 15.3
- name: "GitOps features are now free"
@ -36,7 +36,7 @@
gitlab-com: true
available_in: [Free, Premium, Ultimate]
documentation_link: https://docs.gitlab.com/ee/user/project/merge_requests/reviews/#submit-a-review
image_url: https://about.gitlab.com/images/unreleased/create-mr-review-summary.png
image_url: https://about.gitlab.com/images/15_3/create-mr-review-summary.png
published_at: 2022-08-22
release: 15.3
- name: "Define password complexity requirements"
@ -54,7 +54,7 @@
gitlab-com: false
available_in: [Premium, Ultimate]
documentation_link: https://docs.gitlab.com/ee/user/admin_area/settings/sign_up_restrictions.html#password-complexity-requirements
image_url: https://about.gitlab.com/images/unreleased/manage-password-complexity-policy.png
image_url: https://about.gitlab.com/images/15_3/manage-password-complexity-policy.png
published_at: 2022-08-22
release: 15.3
- name: "Maintain SAML Group Links with API"

View File

@ -0,0 +1,18 @@
# frozen_string_literal: true
class ReplaceIssuesAuthorizationIndex < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
INDEX_NAME = 'idx_open_issues_on_project_and_confidential_and_author_and_id'
OLD_INDEX_NAME = 'idx_open_issues_on_project_id_and_confidential'
def up
add_concurrent_index :issues, [:project_id, :confidential, :author_id, :id], name: INDEX_NAME, where: 'state_id = 1'
remove_concurrent_index_by_name :issues, OLD_INDEX_NAME
end
def down
add_concurrent_index :issues, [:project_id, :confidential], name: OLD_INDEX_NAME, where: 'state_id = 1'
remove_concurrent_index_by_name :issues, INDEX_NAME
end
end

View File

@ -0,0 +1 @@
9df1108b41fdb4546d4c62edffba2a386bcdf486749096b3fb49d289e5c9698d

View File

@ -27440,7 +27440,7 @@ CREATE UNIQUE INDEX idx_on_external_status_checks_project_id_external_url ON ext
CREATE UNIQUE INDEX idx_on_external_status_checks_project_id_name ON external_status_checks USING btree (project_id, name);
CREATE INDEX idx_open_issues_on_project_id_and_confidential ON issues USING btree (project_id, confidential) WHERE (state_id = 1);
CREATE INDEX idx_open_issues_on_project_and_confidential_and_author_and_id ON issues USING btree (project_id, confidential, author_id, id) WHERE (state_id = 1);
CREATE INDEX idx_packages_debian_group_component_files_on_architecture_id ON packages_debian_group_component_files USING btree (architecture_id);

View File

@ -12,8 +12,8 @@ WARNING:
This API is used by the [terraform cli](https://www.terraform.io/)
and is generally not meant for manual consumption.
For instructions on how to upload and install Maven packages from the GitLab
package registry, see the [Terraform modules registry documentation](../../user/packages/terraform_module_registry/index.md).
For instructions on how to upload and install Terraform modules from the GitLab
infrastructure registry, see the [Terraform modules registry documentation](../../user/packages/terraform_module_registry/index.md).
## List available versions for a specific module
@ -114,7 +114,7 @@ Example response:
## Get specific version for a specific module
Get information about the latest version for a given module.
Get information about a specific version for a given module.
```plaintext
GET packages/terraform/modules/v1/:module_namespace/:module_name/:module_system/1.0.0

View File

@ -224,7 +224,7 @@ running `ALTER TABLE` on a non-partitioned table in a few key ways:
## Splitting large partitions into smaller ones
We want to start with the initial `pipeline_id` number `100` (or higher, like
We want to start with the initial `partition_id` number `100` (or higher, like
`1000`, depending on our calculations and estimations). We do not want to start
from 1, because existing tables are also large already, and we might want to
split them into smaller partitions. If we start with `100`, we will be able to
@ -238,6 +238,18 @@ smaller ones (it's not yet clear if we will need to do this), we might be able
to just use background migrations to update partition IDs, and PostgreSQL is
smart enough to move rows between partitions on its own.
### Naming conventions
A partitioned table is called a __routing__ table and it will use the `p_`
prefix which should help us with building automated tooling for query analysis.
A table partition will be simply called __partition__ and it can use the a
physical partition ID as suffix, leaded by a `p` letter, for example
`ci_builds_p101`. Existing CI tables will become __zero partitions__ of the
new routing tables. Depending on the chosen
[partitioning strategy](#how-do-we-want-to-partition-cicd-data) for a given
table, it is possible to have many logical partitions per one physical partition.
## Storing partitions metadata in the database
In order to build an efficient mechanism that will be responsible for creating

View File

@ -31,7 +31,7 @@ To instrument an audit event, the following attributes should be provided:
| Attribute | Type | Required? | Description |
|:-------------|:---------------------|:----------|:------------------------------------------------------------------|
| `name` | String | false | Action name to be audited. Used for error tracking |
| `name` | String | false | Action name to be audited. Represents the [type of the event](#event-type-definitions). Used for error tracking |
| `author` | User | true | User who authors the change |
| `scope` | User, Project, Group | true | Scope which the audit event belongs to |
| `target` | Object | true | Target object being audited |
@ -40,17 +40,15 @@ To instrument an audit event, the following attributes should be provided:
## How to instrument new Audit Events
There are three ways of instrumenting audit events:
1. Create a [YAML type definition](#add-a-new-audit-event-type) for the new audit event.
1. Call `Gitlab::Audit::Auditor.audit`, passing an action block.
The following ways of instrumenting audit events are deprecated:
- Create a new class in `ee/lib/ee/audit/` and extend `AuditEventService`
- Call `AuditEventService` after a successful action
- Call `Gitlab::Audit::Auditor.audit` passing an action block
This inconsistency leads to unexpected bugs, increases maintainer effort, and worsens the
developer experience. Therefore, we suggest you use `Gitlab::Audit::Auditor` to
instrument new audit events.
With new service, we can instrument audit events in two ways:
With `Gitlab::Audit::Auditor` service, we can instrument audit events in two ways:
- Using block for multiple events.
- Using standard method call for single events.
@ -197,6 +195,34 @@ deactivate B
In addition to recording to the database, we also write these events to
[a log file](../../administration/logs/index.md#audit_jsonlog).
## Event type definitions
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/367847) in GitLab 15.4.
All new audit events must have a type definition stored in `config/audit_events/types/` that contains a single source of truth for every auditable event in GitLab.
### Add a new audit event type
To add a new audit event type:
1. Create a new file in `config/audit_events/types/` with the filename matching the name of the event type. For example, a definition for the event type triggered when a
user is added to a project might be stored in `config/audit_events/types/project_add_user.yml`.
1. Add contents to the file that conform to the [schema](#schema) defined in `config/audit_events/types/type_schema.json`.
1. Ensure that all calls to `Gitlab::Audit::Auditor` use the `name` defined in your file.
### Schema
| Field | Required | Description |
| ----- | -------- |--------------|
| `name` | yes | Unique, lowercase and underscored name describing the type of event. Must match the filename. |
| `description` | yes | Human-readable description of how this event is triggered |
| `group` | yes | Name of the group that introduced this audit event. For example, `manage::compliance` |
| `introduced_by_issue` | yes | Issue URL that proposed the addition of this type |
| `introduced_by_mr` | yes | MR URL that added this new type |
| `milestone` | yes | Milestone in which this type was added |
| `saved_to_database` | yes | Indicate whether to persist events to database and JSON logs |
| `streamed` | yes | Indicate that events should be streamed to external services (if configured) |
## Event streaming
All events where the entity is a `Group` or `Project` are recorded in the audit log, and also streamed to one or more

View File

@ -101,7 +101,20 @@ label links in the same worker removes the need for performing a separate crawl
through the API data, reducing the number of API calls necessary to import a
project.
### 8. Stage::ImportNotesWorker
### 8. Stage::ImportIssueEventsWorker
This worker imports all issues and pull request events. For every event, we
schedule a job for the `Gitlab::GithubImport::ImportIssueEventWorker` worker.
We can import both issues and pull request events by single stage because of a specific aspect of the GitHub API. It looks like that under the hood, issues and pull requests
GitHub are stored in a single table. Therefore, they have globally-unique IDs and so:
- Every pull request is an issue.
- Issues aren't pull requests.
Therefore, both issues and pull requests have a common API for most related things.
### 9. Stage::ImportNotesWorker
This worker imports regular comments for both issues and pull requests. For
every comment, we schedule a job for the
@ -112,7 +125,7 @@ returns comments for both issues and pull requests. This means we have to wait
for all issues and pull requests to be imported before we can import regular
comments.
### 9. Stage::FinishImportWorker
### 10. Stage::FinishImportWorker
This worker completes the import process by performing some housekeeping
(such as flushing any caches) and by marking the import as completed.

View File

@ -184,6 +184,8 @@ The following items of a project are imported:
- Pull request "merged by" information (GitLab.com and GitLab 13.7 and later).
- Pull request comments replies in discussions ([GitLab.com and GitLab 14.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/336596)).
- Diff Notes suggestions ([GitLab.com and GitLab 14.7 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/340624)).
- Issue events and pull requests events. [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/7673) in GitLab 15.4 with `github_importer_issue_events_import`
[feature flag](../../../administration/feature_flags.md) disabled by default.
References to pull requests and issues are preserved. Each imported repository maintains visibility level unless that
[visibility level is restricted](../../public_access.md#restrict-use-of-public-or-internal-projects), in which case it

View File

@ -53,7 +53,7 @@ Prerequisites:
To create a task:
1. In an issue description, in the **Tasks** section, select **Add**.
1. In the issue description, in the **Tasks** section, select **Add**.
1. Enter the task title.
1. Select **Create task**.

View File

@ -115,7 +115,7 @@ The **Storage** tab of the **Usage Quotas** page warns you of the following:
### Excess storage example
The following example describes an excess storage scenario for namespace _Example Company_:
The following example describes an excess storage scenario for a namespace:
| Repository | Storage used | Excess storage | Quota | Status |
|------------|--------------|----------------|--------|-------------------|

View File

@ -29,6 +29,19 @@ module Gitlab
def issuable_db_id(object)
IssuableFinder.new(project, object).database_id
end
def issuable_type(issue_event)
merge_request_event?(issue_event) ? MergeRequest.name : Issue.name
end
def merge_request_event?(issue_event)
issue_event.issuable_type == MergeRequest.name
end
def resource_event_belongs_to(issue_event)
belongs_to_key = merge_request_event?(issue_event) ? :merge_request_id : :issue_id
{ belongs_to_key => issuable_db_id(issue_event) }
end
end
end
end

View File

@ -19,7 +19,7 @@ module Gitlab
def create_note(issue_event, note_body, assigner_id)
Note.create!(
system: true,
noteable_type: Issue.name,
noteable_type: issuable_type(issue_event),
noteable_id: issuable_db_id(issue_event),
project: project,
author_id: assigner_id,

View File

@ -12,13 +12,14 @@ module Gitlab
private
def create_event(issue_event)
ResourceLabelEvent.create!(
issue_id: issuable_db_id(issue_event),
attrs = {
user_id: author_id(issue_event),
label_id: label_finder.id_for(issue_event.label_title),
action: action(issue_event.event),
created_at: issue_event.created_at
)
}.merge(resource_event_belongs_to(issue_event))
ResourceLabelEvent.create!(attrs)
end
def label_finder

View File

@ -17,14 +17,15 @@ module Gitlab
private
def create_event(issue_event)
ResourceMilestoneEvent.create!(
issue_id: issuable_db_id(issue_event),
attrs = {
user_id: author_id(issue_event),
created_at: issue_event.created_at,
milestone_id: project.milestones.find_by_title(issue_event.milestone_title)&.id,
action: action(issue_event.event),
state: DEFAULT_STATE
)
}.merge(resource_event_belongs_to(issue_event))
ResourceMilestoneEvent.create!(attrs)
end
def action(event_type)

View File

@ -17,7 +17,7 @@ module Gitlab
project_id: project.id,
author_id: author_id(issue_event),
action: 'closed',
target_type: Issue.name,
target_type: issuable_type(issue_event),
target_id: issuable_db_id(issue_event),
created_at: issue_event.created_at,
updated_at: issue_event.created_at
@ -25,15 +25,16 @@ module Gitlab
end
def create_state_event(issue_event)
ResourceStateEvent.create!(
attrs = {
user_id: author_id(issue_event),
issue_id: issuable_db_id(issue_event),
source_commit: issue_event.commit_id,
state: 'closed',
close_after_error_tracking_resolve: false,
close_auto_resolve_prometheus_alert: false,
created_at: issue_event.created_at
)
}.merge(resource_event_belongs_to(issue_event))
ResourceStateEvent.create!(attrs)
end
end
end

View File

@ -33,7 +33,7 @@ module Gitlab
def create_note(issue_event, note_body, user_id)
Note.create!(
system: true,
noteable_type: Issue.name,
noteable_type: issuable_type(issue_event),
noteable_id: issuable_db_id(issue_event),
project: project,
author_id: user_id,

View File

@ -14,7 +14,7 @@ module Gitlab
def note_params(issue_event)
{
noteable_id: issuable_db_id(issue_event),
noteable_type: Issue.name,
noteable_type: issuable_type(issue_event),
project_id: project.id,
author_id: author_id(issue_event),
note: parse_body(issue_event),

View File

@ -17,7 +17,7 @@ module Gitlab
project_id: project.id,
author_id: author_id(issue_event),
action: 'reopened',
target_type: Issue.name,
target_type: issuable_type(issue_event),
target_id: issuable_db_id(issue_event),
created_at: issue_event.created_at,
updated_at: issue_event.created_at
@ -25,12 +25,13 @@ module Gitlab
end
def create_state_event(issue_event)
ResourceStateEvent.create!(
attrs = {
user_id: author_id(issue_event),
issue_id: issuable_db_id(issue_event),
state: 'reopened',
created_at: issue_event.created_at
)
}.merge(resource_event_belongs_to(issue_event))
ResourceStateEvent.create!(attrs)
end
end
end

View File

@ -15,11 +15,7 @@ module Gitlab
@client = client
end
# TODO: Add MergeRequest events support
# https://gitlab.com/groups/gitlab-org/-/epics/7673
def execute
return if issue_event.issuable_type == 'MergeRequest'
importer = event_importer_class(issue_event)
if importer
importer.new(project, client).execute(issue_event)

View File

@ -7,7 +7,7 @@ module Gitlab
include ParallelScheduling
include SingleEndpointNotesImporting
PROCESSED_PAGE_CACHE_KEY = 'issues/%{issue_iid}/%{collection}'
PROCESSED_PAGE_CACHE_KEY = 'issues/%{issuable_iid}/%{collection}'
BATCH_SIZE = 100
def initialize(project, client, parallel: true)
@ -27,12 +27,20 @@ module Gitlab
Gitlab::GithubImport::ObjectCounter.increment(project, object_type, :fetched)
associated.issue = { 'number' => parent_record.iid }
pull_request = parent_record.is_a? MergeRequest
associated.issue = { 'number' => parent_record.iid, 'pull_request' => pull_request }
yield(associated)
mark_as_imported(associated)
end
# In Github Issues and MergeRequests uses the same API to get their events.
# Even more - they have commonly uniq iid
def each_associated_page(&block)
issues_collection.each_batch(of: BATCH_SIZE, column: :iid) { |batch| process_batch(batch, &block) }
merge_requests_collection.each_batch(of: BATCH_SIZE, column: :iid) { |batch| process_batch(batch, &block) }
end
def importer_class
IssueEventImporter
end
@ -53,16 +61,20 @@ module Gitlab
:issue_timeline
end
def parent_collection
def issues_collection
project.issues.where.not(iid: already_imported_parents).select(:id, :iid) # rubocop: disable CodeReuse/ActiveRecord
end
def merge_requests_collection
project.merge_requests.where.not(iid: already_imported_parents).select(:id, :iid) # rubocop: disable CodeReuse/ActiveRecord
end
def parent_imported_cache_key
"github-importer/issues/#{collection_method}/already-imported/#{project.id}"
end
def page_counter_id(issue)
PROCESSED_PAGE_CACHE_KEY % { issue_iid: issue.iid, collection: collection_method }
def page_counter_id(issuable)
PROCESSED_PAGE_CACHE_KEY % { issuable_iid: issuable.iid, collection: collection_method }
end
def id_for_already_imported_cache(event)
@ -74,10 +86,10 @@ module Gitlab
end
# Cross-referenced events on Github doesn't have id.
def compose_associated_id!(issue, event)
def compose_associated_id!(issuable, event)
return if event.event != 'cross-referenced'
event.id = "cross-reference##{issue.id}-in-#{event.source.issue.id}"
event.id = "cross-reference##{issuable.iid}-in-#{event.source.issue.id}"
end
end
end

View File

@ -63,23 +63,27 @@ module Gitlab
mark_as_imported(associated)
end
def each_associated_page
def each_associated_page(&block)
parent_collection.each_batch(of: BATCH_SIZE, column: :iid) do |batch|
batch.each do |parent_record|
# The page counter needs to be scoped by parent_record to avoid skipping
# pages of notes from already imported parent_record.
page_counter = PageCounter.new(project, page_counter_id(parent_record))
repo = project.import_source
options = collection_options.merge(page: page_counter.current)
process_batch(batch, &block)
end
end
client.each_page(collection_method, repo, parent_record.iid, options) do |page|
next unless page_counter.set(page.number)
def process_batch(batch)
batch.each do |parent_record|
# The page counter needs to be scoped by parent_record to avoid skipping
# pages of notes from already imported parent_record.
page_counter = PageCounter.new(project, page_counter_id(parent_record))
repo = project.import_source
options = collection_options.merge(page: page_counter.current)
yield parent_record, page
end
client.each_page(collection_method, repo, parent_record.iid, options) do |page|
next unless page_counter.set(page.number)
mark_parent_imported(parent_record)
yield parent_record, page
end
mark_parent_imported(parent_record)
end
end

View File

@ -36,6 +36,7 @@ module Gitlab
CATEGORIES_COLLECTED_FROM_METRICS_DEFINITIONS = %w[
ci_users
ci_templates
deploy_token_packages
error_tracking
ide_edit

View File

@ -99,10 +99,6 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- name: p_ci_templates_security_dast_on_demand_api_scan
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- name: p_ci_templates_security_coverage_fuzzing
category: ci_templates
redis_slot: ci_templates
@ -595,10 +591,6 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- name: p_ci_templates_implicit_security_dast_on_demand_api_scan
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- name: p_ci_templates_implicit_security_coverage_fuzzing
category: ci_templates
redis_slot: ci_templates

View File

@ -51,6 +51,19 @@ namespace :gitlab do
File.write(Gitlab::UsageDataCounters::CiTemplateUniqueCounter::KNOWN_EVENTS_FILE_PATH, banner + YAML.dump(all_includes).gsub(/ *$/m, ''))
end
desc 'GitLab | UsageDataMetrics | Generate raw SQL metrics queries for RSpec'
task generate_sql_metrics_queries: :environment do
path = Rails.root.join('tmp', 'test')
queries = Timecop.freeze(2021, 1, 1) do
Gitlab::Usage::ServicePingReport.for(output: :metrics_queries)
end
FileUtils.mkdir_p(path)
FileUtils.chdir(path)
File.write('sql_metrics_queries.json', Gitlab::Json.pretty_generate(queries))
end
def ci_template_includes_hash(source, template_directory = nil)
Gitlab::UsageDataCounters::CiTemplateUniqueCounter.ci_templates("lib/gitlab/ci/templates/#{template_directory}").map do |template|
expanded_template_name = Gitlab::UsageDataCounters::CiTemplateUniqueCounter.expand_template_name("#{template_directory}/#{template}")

View File

@ -11810,9 +11810,6 @@ msgstr ""
msgid "DastConfig|Not enabled"
msgstr ""
msgid "DastProfiles| Profile is currently in-use"
msgstr ""
msgid "DastProfiles|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
msgstr ""
@ -11990,10 +11987,10 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
msgid "DastProfiles|Profile is being used by this on-demand scan"
msgid "DastProfiles|Profile in use and cannot be renamed"
msgstr ""
msgid "DastProfiles|Profile is currently in-use"
msgid "DastProfiles|Profile is being used by this on-demand scan"
msgstr ""
msgid "DastProfiles|Profile name"
@ -26857,6 +26854,9 @@ msgstr ""
msgid "Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{approved_highlight}was approved by%{highlight_end} %{approver_avatar} %{approver_link}"
msgstr ""
msgid "Notify|A new GPG key was added to your account:"
msgstr ""
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@ -26872,6 +26872,15 @@ msgstr ""
msgid "Notify|CI/CD project settings"
msgstr ""
msgid "Notify|Fingerprint: %{fingerprint}"
msgstr ""
msgid "Notify|Hi %{user}!"
msgstr ""
msgid "Notify|If this key was added in error, you can remove it under %{removal_link}"
msgstr ""
msgid "Notify|If you no longer wish to use this domain with GitLab Pages, please remove it from your GitLab project and delete any related DNS records."
msgstr ""
@ -35255,6 +35264,9 @@ msgstr ""
msgid "SecurityOrchestration|This %{namespaceType} does not contain any security policies."
msgstr ""
msgid "SecurityOrchestration|This %{namespaceType} is not linked to a security policy project"
msgstr ""
msgid "SecurityOrchestration|This group"
msgstr ""

View File

@ -34,7 +34,14 @@ describe('~/access_tokens/components/new_access_token_app', () => {
beforeEach(() => {
// NewAccessTokenApp observes a form element
setHTMLFixture(`<form id="${FORM_SELECTOR.slice(1)}"><input type="submit"/></form>`);
setHTMLFixture(
`<form id="${FORM_SELECTOR.slice(1)}">
<input type="text" id="expires_at" value="2022-01-01"/>
<input type="text" value='1'/>
<input type="checkbox" checked/>
<input type="submit"/>
</form>`,
);
createComponent();
});
@ -93,12 +100,15 @@ describe('~/access_tokens/components/new_access_token_app', () => {
});
});
it('should reset the form', async () => {
const resetSpy = jest.spyOn(wrapper.vm.form, 'reset');
it('should reset all input fields except the date', async () => {
expect(document.querySelector('input[type=text][id$=expires_at]').value).toBe('2022-01-01');
expect(document.querySelector('input[type=text]:not([id$=expires_at])').value).toBe('1');
expect(document.querySelector('input[type=checkbox]').checked).toBe(true);
await triggerSuccess();
expect(resetSpy).toHaveBeenCalled();
expect(document.querySelector('input[type=text][id$=expires_at]').value).toBe('2022-01-01');
expect(document.querySelector('input[type=text]:not([id$=expires_at])').value).toBe('');
expect(document.querySelector('input[type=checkbox]').checked).toBe(false);
});
});

View File

@ -7,7 +7,7 @@ RSpec.describe GitlabSchema.types['Timelog'] do
it { expect(described_class.graphql_name).to eq('Timelog') }
it { expect(described_class).to have_graphql_fields(fields) }
it { expect(described_class).to require_graphql_authorizations(:read_issue) }
it { expect(described_class).to require_graphql_authorizations(:read_issuable) }
it { expect(described_class).to expose_permissions_using(Types::PermissionTypes::Timelog) }
describe 'user field' do

View File

@ -0,0 +1,84 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'load_balancing', :delete, :reestablished_active_record_base do
subject(:initialize_load_balancer) do
load Rails.root.join('config/initializers/load_balancing.rb')
end
context 'for a clustered puma worker' do
let!(:group) { create(:group, name: 'my group') }
before do
# Setup host-based load balancing
# Patch in our load balancer config, simply pointing at the test database twice
allow(Gitlab::Database::LoadBalancing::Configuration).to receive(:for_model) do |base_model|
db_host = base_model.connection_pool.db_config.host
Gitlab::Database::LoadBalancing::Configuration.new(base_model, [db_host, db_host])
end
# Pretend we are in clustered environment
allow(Gitlab::Cluster::LifecycleEvents).to receive(:in_clustered_puma?).and_return(true)
# Stub out middleware call, as not idempotent
allow(Gitlab::Application.instance.middleware).to receive(:use)
end
after do
# reset load balancing to original state
allow(Gitlab::Database::LoadBalancing::Configuration).to receive(:for_model).and_call_original
allow(Gitlab::Cluster::LifecycleEvents).to receive(:in_clustered_puma?).and_call_original
load Rails.root.join('config/initializers/load_balancing.rb')
end
it 'configures load balancer to have two replica hosts' do
initialize_load_balancer
simulate_puma_worker do
expect(ApplicationRecord.connection.load_balancer.configuration.hosts.size).to eq(2)
expect(Ci::ApplicationRecord.connection.load_balancer.configuration.hosts.size).to eq(2)
end
end
# We tried using Process.fork for a more realistic simulation
# but run into bugs where GPRC cannot be used before forking processes.
# See https://gitlab.com/gitlab-org/gitlab/-/issues/333184#note_1081658113
def simulate_puma_worker
# Called in https://github.com/rails/rails/blob/6-1-stable/activerecord/lib/active_record/connection_adapters/pool_config.rb#L73
ActiveRecord::ConnectionAdapters::PoolConfig.discard_pools!
# Called in config/puma.rb
Gitlab::Cluster::LifecycleEvents.do_worker_start
yield
end
it 'makes a read query successfully' do
# Clear any previous sticky writes
::Gitlab::Database::LoadBalancing::Session.clear_session
initialize_load_balancer
group_name = simulate_puma_worker do
Group.find_by_name('my group').name
end
expect(group_name).to eq(group.name)
end
it 'makes a write query successfully' do
initialize_load_balancer
expect do
simulate_puma_worker do
Group.touch_all
end
group.reload
end.to change(group, :updated_at)
end
end
end

View File

@ -10,7 +10,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::ChangedAssignee do
let_it_be(:assigner) { create(:user) }
let(:client) { instance_double('Gitlab::GithubImport::Client') }
let(:issue) { create(:issue, project: project) }
let(:issuable) { create(:issue, project: project) }
let(:issue_event) do
Gitlab::GithubImport::Representation::IssueEvent.from_json_hash(
@ -21,14 +21,14 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::ChangedAssignee do
'created_at' => '2022-04-26 18:30:53 UTC',
'assigner' => { 'id' => assigner.id, 'login' => assigner.username },
'assignee' => { 'id' => assignee.id, 'login' => assignee.username },
'issue' => { 'number' => issue.iid }
'issue' => { 'number' => issuable.iid, pull_request: issuable.is_a?(MergeRequest) }
)
end
let(:note_attrs) do
{
noteable_id: issue.id,
noteable_type: Issue.name,
noteable_id: issuable.id,
noteable_type: issuable.class.name,
project_id: project.id,
author_id: assigner.id,
system: true,
@ -45,12 +45,12 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::ChangedAssignee do
}.stringify_keys
end
shared_examples 'new note' do
shared_examples 'create expected notes' do
it 'creates expected note' do
expect { importer.execute(issue_event) }.to change { issue.notes.count }
expect { importer.execute(issue_event) }.to change { issuable.notes.count }
.from(0).to(1)
expect(issue.notes.last)
expect(issuable.notes.last)
.to have_attributes(expected_note_attrs)
end
@ -67,10 +67,26 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::ChangedAssignee do
end
end
shared_examples 'process assigned & unassigned events' do
context 'when importing an assigned event' do
let(:event_type) { 'assigned' }
let(:expected_note_attrs) { note_attrs.merge(note: "assigned to @#{assignee.username}") }
it_behaves_like 'create expected notes'
end
context 'when importing an unassigned event' do
let(:event_type) { 'unassigned' }
let(:expected_note_attrs) { note_attrs.merge(note: "unassigned @#{assigner.username}") }
it_behaves_like 'create expected notes'
end
end
describe '#execute' do
before do
allow_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
allow(finder).to receive(:database_id).and_return(issue.id)
allow(finder).to receive(:database_id).and_return(issuable.id)
end
allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
allow(finder).to receive(:find).with(assignee.id, assignee.username).and_return(assignee.id)
@ -78,18 +94,14 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::ChangedAssignee do
end
end
context 'when importing an assigned event' do
let(:event_type) { 'assigned' }
let(:expected_note_attrs) { note_attrs.merge(note: "assigned to @#{assignee.username}") }
it_behaves_like 'new note'
context 'with Issue' do
it_behaves_like 'process assigned & unassigned events'
end
context 'when importing an unassigned event' do
let(:event_type) { 'unassigned' }
let(:expected_note_attrs) { note_attrs.merge(note: "unassigned @#{assigner.username}") }
context 'with MergeRequest' do
let(:issuable) { create(:merge_request, source_project: project, target_project: project) }
it_behaves_like 'new note'
it_behaves_like 'process assigned & unassigned events'
end
end
end

View File

@ -9,7 +9,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::ChangedLabel do
let_it_be(:user) { create(:user) }
let(:client) { instance_double('Gitlab::GithubImport::Client') }
let(:issue) { create(:issue, project: project) }
let(:issuable) { create(:issue, project: project) }
let!(:label) { create(:label, project: project) }
let(:issue_event) do
@ -19,16 +19,14 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::ChangedLabel do
'event' => event_type,
'commit_id' => nil,
'label_title' => label.title,
'issue_db_id' => issue.id,
'created_at' => '2022-04-26 18:30:53 UTC',
'issue' => { 'number' => issue.iid }
'issue' => { 'number' => issuable.iid, pull_request: issuable.is_a?(MergeRequest) }
)
end
let(:event_attrs) do
{
user_id: user.id,
issue_id: issue.id,
label_id: label.id,
created_at: issue_event.created_at
}.stringify_keys
@ -36,9 +34,9 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::ChangedLabel do
shared_examples 'new event' do
it 'creates a new label event' do
expect { importer.execute(issue_event) }.to change { issue.resource_label_events.count }
expect { importer.execute(issue_event) }.to change { issuable.resource_label_events.count }
.from(0).to(1)
expect(issue.resource_label_events.last)
expect(issuable.resource_label_events.last)
.to have_attributes(expected_event_attrs)
end
end
@ -46,24 +44,44 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::ChangedLabel do
before do
allow(Gitlab::Cache::Import::Caching).to receive(:read_integer).and_return(label.id)
allow_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
allow(finder).to receive(:database_id).and_return(issue.id)
allow(finder).to receive(:database_id).and_return(issuable.id)
end
allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
allow(finder).to receive(:find).with(user.id, user.username).and_return(user.id)
end
end
context 'when importing a labeled event' do
let(:event_type) { 'labeled' }
let(:expected_event_attrs) { event_attrs.merge(action: 'add') }
context 'with Issue' do
context 'when importing a labeled event' do
let(:event_type) { 'labeled' }
let(:expected_event_attrs) { event_attrs.merge(issue_id: issuable.id, action: 'add') }
it_behaves_like 'new event'
it_behaves_like 'new event'
end
context 'when importing an unlabeled event' do
let(:event_type) { 'unlabeled' }
let(:expected_event_attrs) { event_attrs.merge(issue_id: issuable.id, action: 'remove') }
it_behaves_like 'new event'
end
end
context 'when importing an unlabeled event' do
let(:event_type) { 'unlabeled' }
let(:expected_event_attrs) { event_attrs.merge(action: 'remove') }
context 'with MergeRequest' do
let(:issuable) { create(:merge_request, source_project: project, target_project: project) }
it_behaves_like 'new event'
context 'when importing a labeled event' do
let(:event_type) { 'labeled' }
let(:expected_event_attrs) { event_attrs.merge(merge_request_id: issuable.id, action: 'add') }
it_behaves_like 'new event'
end
context 'when importing an unlabeled event' do
let(:event_type) { 'unlabeled' }
let(:expected_event_attrs) { event_attrs.merge(merge_request_id: issuable.id, action: 'remove') }
it_behaves_like 'new event'
end
end
end

View File

@ -9,7 +9,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::ChangedMilestone do
let_it_be(:user) { create(:user) }
let(:client) { instance_double('Gitlab::GithubImport::Client') }
let(:issue) { create(:issue, project: project) }
let(:issuable) { create(:issue, project: project) }
let!(:milestone) { create(:milestone, project: project) }
let(:issue_event) do
@ -19,16 +19,15 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::ChangedMilestone do
'event' => event_type,
'commit_id' => nil,
'milestone_title' => milestone.title,
'issue_db_id' => issue.id,
'issue_db_id' => issuable.id,
'created_at' => '2022-04-26 18:30:53 UTC',
'issue' => { 'number' => issue.iid }
'issue' => { 'number' => issuable.iid, pull_request: issuable.is_a?(MergeRequest) }
)
end
let(:event_attrs) do
{
user_id: user.id,
issue_id: issue.id,
milestone_id: milestone.id,
state: 'opened',
created_at: issue_event.created_at
@ -37,9 +36,9 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::ChangedMilestone do
shared_examples 'new event' do
it 'creates a new milestone event' do
expect { importer.execute(issue_event) }.to change { issue.resource_milestone_events.count }
expect { importer.execute(issue_event) }.to change { issuable.resource_milestone_events.count }
.from(0).to(1)
expect(issue.resource_milestone_events.last)
expect(issuable.resource_milestone_events.last)
.to have_attributes(expected_event_attrs)
end
end
@ -48,25 +47,45 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::ChangedMilestone do
before do
allow(Gitlab::Cache::Import::Caching).to receive(:read_integer).and_return(milestone.id)
allow_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
allow(finder).to receive(:database_id).and_return(issue.id)
allow(finder).to receive(:database_id).and_return(issuable.id)
end
allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
allow(finder).to receive(:find).with(user.id, user.username).and_return(user.id)
end
end
context 'when importing a milestoned event' do
let(:event_type) { 'milestoned' }
let(:expected_event_attrs) { event_attrs.merge(action: 'add') }
context 'with Issue' do
context 'when importing a milestoned event' do
let(:event_type) { 'milestoned' }
let(:expected_event_attrs) { event_attrs.merge(issue_id: issuable.id, action: 'add') }
it_behaves_like 'new event'
it_behaves_like 'new event'
end
context 'when importing demilestoned event' do
let(:event_type) { 'demilestoned' }
let(:expected_event_attrs) { event_attrs.merge(issue_id: issuable.id, action: 'remove') }
it_behaves_like 'new event'
end
end
context 'when importing demilestoned event' do
let(:event_type) { 'demilestoned' }
let(:expected_event_attrs) { event_attrs.merge(action: 'remove') }
context 'with MergeRequest' do
let(:issuable) { create(:merge_request, source_project: project, target_project: project) }
it_behaves_like 'new event'
context 'when importing a milestoned event' do
let(:event_type) { 'milestoned' }
let(:expected_event_attrs) { event_attrs.merge(merge_request_id: issuable.id, action: 'add') }
it_behaves_like 'new event'
end
context 'when importing demilestoned event' do
let(:event_type) { 'demilestoned' }
let(:expected_event_attrs) { event_attrs.merge(merge_request_id: issuable.id, action: 'remove') }
it_behaves_like 'new event'
end
end
end
end

View File

@ -9,7 +9,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Closed do
let_it_be(:user) { create(:user) }
let(:client) { instance_double('Gitlab::GithubImport::Client') }
let(:issue) { create(:issue, project: project) }
let(:issuable) { create(:issue, project: project) }
let(:commit_id) { nil }
let(:issue_event) do
@ -21,7 +21,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Closed do
'event' => 'closed',
'created_at' => '2022-04-26 18:30:53 UTC',
'commit_id' => commit_id,
'issue' => { 'number' => issue.iid }
'issue' => { 'number' => issuable.iid, pull_request: issuable.is_a?(MergeRequest) }
)
end
@ -29,54 +29,74 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Closed do
{
project_id: project.id,
author_id: user.id,
target_id: issue.id,
target_type: Issue.name,
target_id: issuable.id,
target_type: issuable.class.name,
action: 'closed',
created_at: issue_event.created_at,
updated_at: issue_event.created_at
}.stringify_keys
end
let(:expected_state_event_attrs) do
{
user_id: user.id,
issue_id: issue.id,
state: 'closed',
created_at: issue_event.created_at
}.stringify_keys
end
before do
allow_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
allow(finder).to receive(:database_id).and_return(issue.id)
allow(finder).to receive(:database_id).and_return(issuable.id)
end
allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
allow(finder).to receive(:find).with(user.id, user.username).and_return(user.id)
end
end
it 'creates expected event and state event' do
importer.execute(issue_event)
expect(issue.events.count).to eq 1
expect(issue.events[0].attributes)
.to include expected_event_attrs
expect(issue.resource_state_events.count).to eq 1
expect(issue.resource_state_events[0].attributes)
.to include expected_state_event_attrs
end
context 'when closed by commit' do
let!(:closing_commit) { create(:commit, project: project) }
let(:commit_id) { closing_commit.id }
shared_examples 'new event' do
it 'creates expected event and state event' do
importer.execute(issue_event)
expect(issue.events.count).to eq 1
state_event = issue.resource_state_events.last
expect(state_event.source_commit).to eq commit_id[0..40]
expect(issuable.events.count).to eq 1
expect(issuable.events[0].attributes)
.to include expected_event_attrs
expect(issuable.resource_state_events.count).to eq 1
expect(issuable.resource_state_events[0].attributes)
.to include expected_state_event_attrs
end
context 'when closed by commit' do
let!(:closing_commit) { create(:commit, project: project) }
let(:commit_id) { closing_commit.id }
it 'creates expected event and state event' do
importer.execute(issue_event)
expect(issuable.events.count).to eq 1
state_event = issuable.resource_state_events.last
expect(state_event.source_commit).to eq commit_id[0..40]
end
end
end
context 'with Issue' do
let(:expected_state_event_attrs) do
{
user_id: user.id,
issue_id: issuable.id,
state: 'closed',
created_at: issue_event.created_at
}.stringify_keys
end
it_behaves_like 'new event'
end
context 'with MergeRequest' do
let(:issuable) { create(:merge_request, source_project: project, target_project: project) }
let(:expected_state_event_attrs) do
{
user_id: user.id,
merge_request_id: issuable.id,
state: 'closed',
created_at: issue_event.created_at
}.stringify_keys
end
it_behaves_like 'new event'
end
end

View File

@ -9,9 +9,8 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::CrossReferenced, :clean_g
let_it_be(:user) { create(:user) }
let(:client) { instance_double('Gitlab::GithubImport::Client') }
let(:issue_iid) { 999 }
let(:issue) { create(:issue, project: project, iid: issue_iid) }
let(:issuable) { create(:issue, project: project, iid: issue_iid) }
let(:referenced_in) { build_stubbed(:issue, project: project, iid: issue_iid + 1) }
let(:commit_id) { nil }
@ -30,7 +29,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::CrossReferenced, :clean_g
}
},
'created_at' => '2022-04-26 18:30:53 UTC',
'issue' => { 'number' => issue.iid }
'issue' => { 'number' => issuable.iid, pull_request: issuable.is_a?(MergeRequest) }
)
end
@ -38,8 +37,8 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::CrossReferenced, :clean_g
let(:expected_note_attrs) do
{
system: true,
noteable_type: Issue.name,
noteable_id: issue.id,
noteable_type: issuable.class.name,
noteable_id: issuable.id,
project_id: project.id,
author_id: user.id,
note: expected_note_body,
@ -47,58 +46,70 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::CrossReferenced, :clean_g
}.stringify_keys
end
context 'when referenced in other issue' do
let(:expected_note_body) { "mentioned in issue ##{referenced_in.iid}" }
shared_examples 'import cross-referenced event' do
context 'when referenced in other issue' do
let(:expected_note_body) { "mentioned in issue ##{referenced_in.iid}" }
before do
allow_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
allow(finder).to receive(:database_id).and_return(referenced_in.iid)
allow(finder).to receive(:database_id).and_return(issue.id)
before do
allow_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
allow(finder).to receive(:database_id).and_return(referenced_in.iid)
allow(finder).to receive(:database_id).and_return(issuable.id)
end
allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
allow(finder).to receive(:find).with(user.id, user.username).and_return(user.id)
end
end
allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
allow(finder).to receive(:find).with(user.id, user.username).and_return(user.id)
it 'creates expected note' do
importer.execute(issue_event)
expect(issuable.notes.count).to eq 1
expect(issuable.notes[0]).to have_attributes expected_note_attrs
expect(issuable.notes[0].system_note_metadata.action).to eq 'cross_reference'
end
end
it 'creates expected note' do
importer.execute(issue_event)
context 'when referenced in pull request' do
let(:referenced_in) { build_stubbed(:merge_request, project: project) }
let(:pull_request_resource) { { 'id' => referenced_in.iid } }
expect(issue.notes.count).to eq 1
expect(issue.notes[0]).to have_attributes expected_note_attrs
expect(issue.notes[0].system_note_metadata.action).to eq 'cross_reference'
let(:expected_note_body) { "mentioned in merge request !#{referenced_in.iid}" }
before do
allow_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
allow(finder).to receive(:database_id).and_return(referenced_in.iid)
allow(finder).to receive(:database_id).and_return(issuable.id)
end
allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
allow(finder).to receive(:find).with(user.id, user.username).and_return(user.id)
end
end
it 'creates expected note' do
importer.execute(issue_event)
expect(issuable.notes.count).to eq 1
expect(issuable.notes[0]).to have_attributes expected_note_attrs
expect(issuable.notes[0].system_note_metadata.action).to eq 'cross_reference'
end
end
context 'when referenced in out of project issue/pull_request' do
it 'does not create expected note' do
importer.execute(issue_event)
expect(issuable.notes.count).to eq 0
end
end
end
context 'when referenced in pull request' do
let(:referenced_in) { build_stubbed(:merge_request, project: project) }
let(:pull_request_resource) { { 'id' => referenced_in.iid } }
let(:expected_note_body) { "mentioned in merge request !#{referenced_in.iid}" }
before do
allow_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
allow(finder).to receive(:database_id).and_return(referenced_in.iid)
allow(finder).to receive(:database_id).and_return(issue.id)
end
allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
allow(finder).to receive(:find).with(user.id, user.username).and_return(user.id)
end
end
it 'creates expected note' do
importer.execute(issue_event)
expect(issue.notes.count).to eq 1
expect(issue.notes[0]).to have_attributes expected_note_attrs
expect(issue.notes[0].system_note_metadata.action).to eq 'cross_reference'
end
context 'with Issue' do
it_behaves_like 'import cross-referenced event'
end
context 'when referenced in out of project issue/pull_request' do
it 'does not create expected note' do
importer.execute(issue_event)
context 'with MergeRequest' do
let(:issuable) { create(:merge_request, source_project: project, target_project: project) }
expect(issue.notes.count).to eq 0
end
it_behaves_like 'import cross-referenced event'
end
end

View File

@ -8,7 +8,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Renamed do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
let(:issue) { create(:issue, project: project) }
let(:issuable) { create(:issue, project: project) }
let(:client) { instance_double('Gitlab::GithubImport::Client') }
let(:issue_event) do
@ -20,14 +20,14 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Renamed do
'created_at' => '2022-04-26 18:30:53 UTC',
'old_title' => 'old title',
'new_title' => 'new title',
'issue' => { 'number' => issue.iid }
'issue' => { 'number' => issuable.iid, pull_request: issuable.is_a?(MergeRequest) }
)
end
let(:expected_note_attrs) do
{
noteable_id: issue.id,
noteable_type: Issue.name,
noteable_id: issuable.id,
noteable_type: issuable.class.name,
project_id: project.id,
author_id: user.id,
note: "changed title from **{-old-} title** to **{+new+} title**",
@ -48,31 +48,43 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Renamed do
describe '#execute' do
before do
allow_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
allow(finder).to receive(:database_id).and_return(issue.id)
allow(finder).to receive(:database_id).and_return(issuable.id)
end
allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
allow(finder).to receive(:find).with(user.id, user.username).and_return(user.id)
end
end
it 'creates expected note' do
expect { importer.execute(issue_event) }.to change { issue.notes.count }
.from(0).to(1)
expect(issue.notes.last)
.to have_attributes(expected_note_attrs)
end
it 'creates expected system note metadata' do
expect { importer.execute(issue_event) }.to change { SystemNoteMetadata.count }
shared_examples 'import renamed event' do
it 'creates expected note' do
expect { importer.execute(issue_event) }.to change { issuable.notes.count }
.from(0).to(1)
expect(SystemNoteMetadata.last)
.to have_attributes(
expected_system_note_metadata_attrs.merge(
note_id: Note.last.id
expect(issuable.notes.last)
.to have_attributes(expected_note_attrs)
end
it 'creates expected system note metadata' do
expect { importer.execute(issue_event) }.to change { SystemNoteMetadata.count }
.from(0).to(1)
expect(SystemNoteMetadata.last)
.to have_attributes(
expected_system_note_metadata_attrs.merge(
note_id: Note.last.id
)
)
)
end
end
context 'with Issue' do
it_behaves_like 'import renamed event'
end
context 'with MergeRequest' do
let(:issuable) { create(:merge_request, source_project: project, target_project: project) }
it_behaves_like 'import renamed event'
end
end
end

View File

@ -9,7 +9,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Reopened, :aggregate_fail
let_it_be(:user) { create(:user) }
let(:client) { instance_double('Gitlab::GithubImport::Client') }
let(:issue) { create(:issue, project: project) }
let(:issuable) { create(:issue, project: project) }
let(:issue_event) do
Gitlab::GithubImport::Representation::IssueEvent.from_json_hash(
@ -19,7 +19,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Reopened, :aggregate_fail
'actor' => { 'id' => user.id, 'login' => user.username },
'event' => 'reopened',
'created_at' => '2022-04-26 18:30:53 UTC',
'issue' => { 'number' => issue.iid }
'issue' => { 'number' => issuable.iid, pull_request: issuable.is_a?(MergeRequest) }
)
end
@ -27,40 +27,61 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Reopened, :aggregate_fail
{
project_id: project.id,
author_id: user.id,
target_id: issue.id,
target_type: Issue.name,
target_id: issuable.id,
target_type: issuable.class.name,
action: 'reopened',
created_at: issue_event.created_at,
updated_at: issue_event.created_at
}.stringify_keys
end
let(:expected_state_event_attrs) do
{
user_id: user.id,
state: 'reopened',
created_at: issue_event.created_at
}.stringify_keys
end
before do
allow_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
allow(finder).to receive(:database_id).and_return(issue.id)
allow(finder).to receive(:database_id).and_return(issuable.id)
end
allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
allow(finder).to receive(:find).with(user.id, user.username).and_return(user.id)
end
end
it 'creates expected event and state event' do
importer.execute(issue_event)
shared_examples 'new event' do
it 'creates expected event and state event' do
importer.execute(issue_event)
expect(issue.events.count).to eq 1
expect(issue.events[0].attributes)
.to include expected_event_attrs
expect(issuable.events.count).to eq 1
expect(issuable.events[0].attributes)
.to include expected_event_attrs
expect(issue.resource_state_events.count).to eq 1
expect(issue.resource_state_events[0].attributes)
.to include expected_state_event_attrs
expect(issuable.resource_state_events.count).to eq 1
expect(issuable.resource_state_events[0].attributes)
.to include expected_state_event_attrs
end
end
context 'with Issue' do
let(:expected_state_event_attrs) do
{
user_id: user.id,
issue_id: issuable.id,
state: 'reopened',
created_at: issue_event.created_at
}.stringify_keys
end
it_behaves_like 'new event'
end
context 'with MergeRequest' do
let(:issuable) { create(:merge_request, source_project: project, target_project: project) }
let(:expected_state_event_attrs) do
{
user_id: user.id,
merge_request_id: issuable.id,
state: 'reopened',
created_at: issue_event.created_at
}.stringify_keys
end
it_behaves_like 'new event'
end
end

View File

@ -42,10 +42,6 @@ RSpec.describe Gitlab::GithubImport::Importer::IssueEventImporter, :clean_gitlab
end
describe '#execute' do
before do
issue_event.attributes[:issue_db_id] = issue.id
end
context "when it's closed issue event" do
let(:event_name) { 'closed' }

View File

@ -6,7 +6,8 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter
let(:client) { double }
let_it_be(:project) { create(:project, :import_started, import_source: 'http://somegithub.com') }
let_it_be(:issue) { create(:issue, project: project) }
let!(:issuable) { create(:issue, project: project) }
subject { described_class.new(project, client, parallel: parallel) }
@ -35,7 +36,7 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter
end
describe '#page_counter_id' do
it { expect(subject.page_counter_id(issue)).to eq("issues/#{issue.iid}/issue_timeline") }
it { expect(subject.page_counter_id(issuable)).to eq("issues/#{issuable.iid}/issue_timeline") }
end
describe '#id_for_already_imported_cache' do
@ -51,6 +52,39 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter
end
end
describe '#compose_associated_id!' do
let(:issuable) { build_stubbed(:issue, iid: 99) }
let(:event_resource) { Struct.new(:id, :event, :source, keyword_init: true) }
context 'when event type is cross-referenced' do
let(:event) do
source_resource = Struct.new(:issue, keyword_init: true)
issue_resource = Struct.new(:id, keyword_init: true)
event_resource.new(
id: nil,
event: 'cross-referenced',
source: source_resource.new(issue: issue_resource.new(id: '100500'))
)
end
it 'assigns event id' do
subject.compose_associated_id!(issuable, event)
expect(event.id).to eq 'cross-reference#99-in-100500'
end
end
context "when event type isn't cross-referenced" do
let(:event) { event_resource.new(id: nil, event: 'labeled') }
it "doesn't assign event id" do
subject.compose_associated_id!(issuable, event)
expect(event.id).to eq nil
end
end
end
describe '#each_object_to_import', :clean_gitlab_redis_cache do
let(:issue_event) do
struct = Struct.new(:id, :event, :created_at, :issue, keyword_init: true)
@ -72,19 +106,37 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter
.with(
:issue_timeline,
project.import_source,
issue.iid,
issuable.iid,
{ state: 'all', sort: 'created', direction: 'asc', page: 1 }
).and_yield(page)
end
it 'imports each issue event page by page' do
counter = 0
subject.each_object_to_import do |object|
expect(object).to eq issue_event
expect(issue_event.issue['number']).to eq issue.iid
counter += 1
context 'with issues' do
it 'imports each issue event page by page' do
counter = 0
subject.each_object_to_import do |object|
expect(object).to eq issue_event
expect(issue_event.issue['number']).to eq issuable.iid
expect(issue_event.issue['pull_request']).to eq false
counter += 1
end
expect(counter).to eq 1
end
end
context 'with merge requests' do
let!(:issuable) { create(:merge_request, source_project: project, target_project: project) }
it 'imports each merge request event page by page' do
counter = 0
subject.each_object_to_import do |object|
expect(object).to eq issue_event
expect(issue_event.issue['number']).to eq issuable.iid
expect(issue_event.issue['pull_request']).to eq true
counter += 1
end
expect(counter).to eq 1
end
expect(counter).to eq 1
end
it 'triggers page number increment' do
@ -103,7 +155,7 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter
context 'when page is already processed' do
before do
page_counter = Gitlab::GithubImport::PageCounter.new(
project, subject.page_counter_id(issue)
project, subject.page_counter_id(issuable)
)
page_counter.set(page.number)
end

View File

@ -18,8 +18,8 @@ RSpec.describe IssuablePolicy, models: true do
project.add_reporter(reporter)
end
def permissions(user, issue)
described_class.new(user, issue)
def permissions(user, issuable)
described_class.new(user, issuable)
end
describe '#rules' do
@ -153,5 +153,55 @@ RSpec.describe IssuablePolicy, models: true do
expect(permissions(reporter, issue)).to be_allowed(:create_timelog)
end
end
context 'when subject is a Merge Request' do
let(:issuable) { create(:merge_request) }
let(:policy) { permissions(user, issuable) }
before do
allow(policy).to receive(:can?).with(:read_merge_request).and_return(can_read_merge_request)
end
context 'when can_read_merge_request is false' do
let(:can_read_merge_request) { false }
it 'does not allow :read_issuable' do
expect(policy).not_to be_allowed(:read_issuable)
end
end
context 'when can_read_merge_request is true' do
let(:can_read_merge_request) { true }
it 'allows :read_issuable' do
expect(policy).to be_allowed(:read_issuable)
end
end
end
context 'when subject is an Issue' do
let(:issuable) { create(:issue) }
let(:policy) { permissions(user, issuable) }
before do
allow(policy).to receive(:can?).with(:read_issue).and_return(can_read_issue)
end
context 'when can_read_issue is false' do
let(:can_read_issue) { false }
it 'does not allow :read_issuable' do
expect(policy).not_to be_allowed(:read_issuable)
end
end
context 'when can_read_issue is true' do
let(:can_read_issue) { true }
it 'allows :read_issuable' do
expect(policy).to be_allowed(:read_issuable)
end
end
end
end
end

View File

@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
require 'rake_helper'
RSpec.describe API::UsageDataQueries do
include UsageDataHelpers
@ -64,5 +65,36 @@ RSpec.describe API::UsageDataQueries do
expect(response).to have_gitlab_http_status(:forbidden)
end
end
context 'when querying sql metrics' do
let(:file) { Rails.root.join('tmp', 'test', 'sql_metrics_queries.json') }
before do
Rake.application.rake_require 'tasks/gitlab/usage_data'
run_rake_task('gitlab:usage_data:generate_sql_metrics_queries')
end
after do
FileUtils.rm_rf(file)
end
it 'matches the generated query' do
Timecop.freeze(2021, 1, 1) do
get api(endpoint, admin)
end
data = Gitlab::Json.parse(File.read(file))
expect(
json_response['counts_monthly'].except('aggregated_metrics')
).to eq(data['counts_monthly'].except('aggregated_metrics'))
expect(json_response['counts']).to eq(data['counts'])
expect(json_response['active_user_count']).to eq(data['active_user_count'])
expect(json_response['usage_activity_by_stage']).to eq(data['usage_activity_by_stage'])
expect(json_response['usage_activity_by_stage_monthly']).to eq(data['usage_activity_by_stage_monthly'])
end
end
end
end

View File

@ -555,24 +555,29 @@ RSpec.describe Issues::CreateService do
expect(reloaded_discussion.last_note.system).to eq(true)
end
it 'assigns the title and description for the issue' do
issue = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
it 'sets default title and description values if not provided' do
issue = described_class.new(
project: project, current_user: user,
params: opts,
spam_params: spam_params
).execute
expect(issue.title).not_to be_nil
expect(issue.description).not_to be_nil
expect(issue).to be_persisted
expect(issue.title).to eq("Follow-up from \"#{merge_request.title}\"")
expect(issue.description).to include("The following discussion from #{merge_request.to_reference} should be addressed")
end
it 'can set nil explicitly to the title and description' do
it 'takes params from the request over the default values' do
issue = described_class.new(project: project, current_user: user,
params: {
merge_request_to_resolve_discussions_of: merge_request,
description: nil,
title: nil
},
params: opts.merge(
description: 'Custom issue description',
title: 'My new issue'
),
spam_params: spam_params).execute
expect(issue.description).to be_nil
expect(issue.title).to be_nil
expect(issue).to be_persisted
expect(issue.description).to eq('Custom issue description')
expect(issue.title).to eq('My new issue')
end
end
@ -594,24 +599,29 @@ RSpec.describe Issues::CreateService do
expect(reloaded_discussion.last_note.system).to eq(true)
end
it 'assigns the title and description for the issue' do
issue = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
it 'sets default title and description values if not provided' do
issue = described_class.new(
project: project, current_user: user,
params: opts,
spam_params: spam_params
).execute
expect(issue.title).not_to be_nil
expect(issue.description).not_to be_nil
expect(issue).to be_persisted
expect(issue.title).to eq("Follow-up from \"#{merge_request.title}\"")
expect(issue.description).to include("The following discussion from #{merge_request.to_reference} should be addressed")
end
it 'can set nil explicitly to the title and description' do
it 'takes params from the request over the default values' do
issue = described_class.new(project: project, current_user: user,
params: {
merge_request_to_resolve_discussions_of: merge_request,
description: nil,
title: nil
},
params: opts.merge(
description: 'Custom issue description',
title: 'My new issue'
),
spam_params: spam_params).execute
expect(issue.description).to be_nil
expect(issue.title).to be_nil
expect(issue).to be_persisted
expect(issue.description).to eq('Custom issue description')
expect(issue.title).to eq('My new issue')
end
end
end

View File

@ -5,13 +5,20 @@ require 'rake_helper'
RSpec.describe 'gitlab:usage data take tasks', :silence_stdout do
include UsageDataHelpers
let(:metrics_file) { Rails.root.join('tmp', 'test', 'sql_metrics_queries.json') }
before do
Rake.application.rake_require 'tasks/gitlab/usage_data'
# stub prometheus external http calls https://gitlab.com/gitlab-org/gitlab/-/issues/245277
stub_prometheus_queries
stub_database_flavor_check
end
after do
FileUtils.rm_rf(metrics_file)
end
describe 'dump_sql_in_yaml' do
it 'dumps SQL queries in yaml format' do
expect { run_rake_task('gitlab:usage_data:dump_sql_in_yaml') }.to output(/.*recorded_at:.*/).to_stdout
@ -23,4 +30,12 @@ RSpec.describe 'gitlab:usage data take tasks', :silence_stdout do
expect { run_rake_task('gitlab:usage_data:dump_sql_in_json') }.to output(/.*"recorded_at":.*/).to_stdout
end
end
describe 'generate_sql_metrics_fixture' do
it 'generates fixture file correctly' do
run_rake_task('gitlab:usage_data:generate_sql_metrics_queries')
expect(Pathname.new(metrics_file)).to exist
end
end
end

View File

@ -47,7 +47,7 @@
- 'jira_connect/'
- 'kubernetes/'
- 'protected_environments/'
- '/config/feature_flags/development/jira_connect_*'
- '/config/feature_flags/**/*'
- '/config/metrics/'
- '/app/controllers/groups/dependency_proxy_auth_controller.rb'
- '/app/finders/ci/auth_job_finder.rb'
@ -65,17 +65,19 @@
keywords:
- audit
patterns:
- '**%{keyword}**'
- '/{,ee/}app/**/*%{keyword}*'
- '/{,ee/}config/**/*%{keyword}*'
- '/{,ee/}lib/**/*%{keyword}*'
deny:
keywords:
- '*.png'
- '*bundler-audit*'
- '**/merge_requests/**'
- '/ee/app/services/audit_events/*'
- '/config/feature_flags/**/*'
- '/ee/app/services/audit_events/**/*'
- '/ee/config/feature_flags/development/auditor_group_runner_access.yml'
- '/ee/spec/services/audit_events/*'
- '/ee/spec/services/audit_events/**/*'
- '/ee/spec/services/ci/*'
- '/ee/spec/services/personal_access_tokens/*'
- '/qa/**/*'
patterns:
- '%{keyword}'