summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/issue_templates/Feature proposal.md22
-rw-r--r--.rubocop.yml3
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue2
-rw-r--r--app/assets/stylesheets/utilities.scss6
-rw-r--r--app/graphql/types/snippet_type.rb2
-rw-r--r--app/models/project_wiki.rb1
-rw-r--r--app/models/snippet.rb2
-rw-r--r--app/models/user.rb28
-rw-r--r--app/policies/base_policy.rb3
-rw-r--r--changelogs/unreleased/213136-move-features-to-core-design-management.yml5
-rw-r--r--changelogs/unreleased/changelog-spec.yml5
-rw-r--r--changelogs/unreleased/feat-x509-signatures-api-endpoint.yml5
-rw-r--r--changelogs/unreleased/jivanvl-replace-refresh-icon-monitoring-dashboard.yml5
-rw-r--r--changelogs/unreleased/vij-snippet-repo-urls-fix.yml5
-rw-r--r--doc/api/commits.md28
-rw-r--r--doc/ci/variables/README.md6
-rw-r--r--doc/development/testing_guide/frontend_testing.md31
-rw-r--r--doc/user/permissions.md4
-rw-r--r--doc/user/project/issue_board.md5
-rw-r--r--doc/user/project/issues/design_management.md2
-rw-r--r--doc/user/project/issues/index.md2
-rw-r--r--doc/user/project/settings/import_export.md2
-rw-r--r--lib/api/commits.rb8
-rw-r--r--lib/api/entities/commit_signature.rb12
-rw-r--r--lib/api/entities/gpg_commit_signature.rb12
-rw-r--r--lib/api/entities/x509_certificate.rb15
-rw-r--r--lib/api/entities/x509_issuer.rb12
-rw-r--r--lib/api/entities/x509_signature.rb10
-rw-r--r--locale/gitlab.pot6
-rw-r--r--package.json2
-rw-r--r--spec/controllers/concerns/controller_with_cross_project_access_check_spec.rb1
-rw-r--r--spec/controllers/graphql_controller_spec.rb1
-rw-r--r--spec/controllers/groups/boards_controller_spec.rb4
-rw-r--r--spec/controllers/projects/boards_controller_spec.rb4
-rw-r--r--spec/factories/ci/builds.rb5
-rw-r--r--spec/factories/internal_ids.rb6
-rw-r--r--spec/factories/issues.rb2
-rw-r--r--spec/factories/merge_requests.rb2
-rw-r--r--spec/factories/milestones.rb2
-rw-r--r--spec/factories/notes.rb14
-rw-r--r--spec/factories/sequences.rb1
-rw-r--r--spec/frontend/fixtures/snippet.rb2
-rw-r--r--spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap2
-rw-r--r--spec/graphql/types/snippet_type_spec.rb52
-rw-r--r--spec/helpers/events_helper_spec.rb2
-rw-r--r--spec/lib/gitlab/danger/changelog_spec.rb14
-rw-r--r--spec/lib/gitlab/gfm/reference_rewriter_spec.rb8
-rw-r--r--spec/models/user_spec.rb69
-rw-r--r--spec/requests/api/commits_spec.rb28
-rw-r--r--spec/requests/api/discussions_spec.rb2
-rw-r--r--spec/support/helpers/repo_helpers.rb4
-rw-r--r--yarn.lock8
52 files changed, 360 insertions, 124 deletions
diff --git a/.gitlab/issue_templates/Feature proposal.md b/.gitlab/issue_templates/Feature proposal.md
index 2bbef723b21..4b98b4e7ac6 100644
--- a/.gitlab/issue_templates/Feature proposal.md
+++ b/.gitlab/issue_templates/Feature proposal.md
@@ -1,11 +1,15 @@
+<!-- The first three sections: "Problem to solve", "Intended users" and "Proposal", are strongly recommended, while the rest of the sections can be filled out during the problem validation or breakdown phase. However, keep in mind that providing complete and relevant information early helps our product team validate the problem and start working on a solution. -->
+
### Problem to solve
-<!-- What problem do we solve? -->
+<!-- What problem do we solve? Try to define the who/what/why of the opportunity as a user story. For example, "As a (who), I want (what), so I can (why/value)." -->
### Intended users
<!-- Who will use this feature? If known, include any of the following: types of users (e.g. Developer), personas, or specific company roles (e.g. Release Manager). It's okay to write "Unknown" and fill this field in later.
+Personas are described at https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/
+
* [Rachel (Release Manager)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#rachel-release-manager)
* [Parker (Product Manager)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#parker-product-manager)
* [Delaney (Development Team Lead)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#delaney-development-team-lead)
@@ -16,13 +20,11 @@
* [Sam (Security Analyst)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#sam-security-analyst)
* [Dana (Data Analyst)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#dana-data-analyst)
* [Simone (Software Engineer in Test)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#simone-software-engineer-in-test)
-* [Allison (Application Ops)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#allison-application-ops)
-
-Personas are described at https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/ -->
+* [Allison (Application Ops)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#allison-application-ops) -->
### Further details
-<!-- Include use cases, benefits, and/or goals (contributes to our vision?) -->
+<!-- Include use cases, benefits, goals, or any other details that will help us understand the problem better. -->
### Proposal
@@ -35,14 +37,15 @@ Personas are described at https://about.gitlab.com/handbook/marketing/product-ma
### Documentation
<!-- See the Feature Change Documentation Workflow https://docs.gitlab.com/ee/development/documentation/feature-change-workflow.html
-Add all known Documentation Requirements here, per https://docs.gitlab.com/ee/development/documentation/feature-change-workflow.html#documentation-requirements
-If this feature requires changing permissions, this document https://docs.gitlab.com/ee/user/permissions.html must be updated accordingly. -->
+
+* Add all known Documentation Requirements in this section. See https://docs.gitlab.com/ee/development/documentation/feature-change-workflow.html#documentation-requirements
+* If this feature requires changing permissions, update the permissions document. See https://docs.gitlab.com/ee/user/permissions.html -->
### Availability & Testing
<!-- This section needs to be retained and filled in during the workflow planning breakdown phase of this feature proposal, if not earlier.
- What risks does this change pose to our availability? How might it affect the quality of the product? What additional test coverage or changes to tests will be needed? Will it require cross-browser testing?
+What risks does this change pose to our availability? How might it affect the quality of the product? What additional test coverage or changes to tests will be needed? Will it require cross-browser testing?
Please list the test areas (unit, integration and end-to-end) that needs to be added or updated to ensure that this feature will work as intended. Please use the list below as guidance.
* Unit test changes
@@ -57,7 +60,8 @@ See the test engineering planning process and reach out to your counterpart Soft
### What is the type of buyer?
-<!-- Which leads to: in which enterprise tier should this feature go? See https://about.gitlab.com/handbook/product/pricing/#four-tiers -->
+<!-- What is the buyer persona for this feature? See https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/buyer-persona/
+In which enterprise tier should this feature go? See https://about.gitlab.com/handbook/product/pricing/#four-tiers -->
### Is this a cross-stage feature?
diff --git a/.rubocop.yml b/.rubocop.yml
index 4262fd9ca74..830503a1497 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -217,12 +217,10 @@ Gitlab/DuplicateSpecLocation:
- ee/spec/helpers/auth_helper_spec.rb
- ee/spec/lib/gitlab/gl_repository_spec.rb
- ee/spec/models/namespace_spec.rb
- - ee/spec/services/merge_requests/create_service_spec.rb
- ee/spec/services/merge_requests/refresh_service_spec.rb
- ee/spec/services/merge_requests/update_service_spec.rb
- ee/spec/helpers/ee/auth_helper_spec.rb
- ee/spec/models/ee/namespace_spec.rb
- - ee/spec/services/ee/merge_requests/create_service_spec.rb
- ee/spec/services/ee/merge_requests/refresh_service_spec.rb
- ee/spec/services/ee/merge_requests/update_service_spec.rb
@@ -398,7 +396,6 @@ RSpec/RepeatedExample:
- 'spec/graphql/gitlab_schema_spec.rb'
- 'spec/helpers/users_helper_spec.rb'
- 'spec/lib/gitlab/closing_issue_extractor_spec.rb'
- - 'spec/lib/gitlab/danger/changelog_spec.rb'
- 'spec/lib/gitlab/import_export/project/relation_factory_spec.rb'
- 'spec/rubocop/cop/migration/update_large_table_spec.rb'
- 'spec/services/notification_service_spec.rb'
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index 2229b6d8292..9db29f327da 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -478,7 +478,7 @@ export default {
:title="s__('Metrics|Reload this page')"
@click="refreshDashboard"
>
- <icon name="repeat" />
+ <icon name="retry" />
</gl-deprecated-button>
</gl-form-group>
diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss
index 925c15262e9..0a1e97d1252 100644
--- a/app/assets/stylesheets/utilities.scss
+++ b/app/assets/stylesheets/utilities.scss
@@ -76,10 +76,16 @@
.gl-bg-green-100 { @include gl-bg-green-100;}
.gl-text-blue-500 { @include gl-text-blue-500; }
+.gl-text-gray-500 { @include gl-text-gray-500; }
.gl-text-gray-700 { @include gl-text-gray-700; }
.gl-text-gray-900 { @include gl-text-gray-900; }
.gl-text-red-700 { @include gl-text-red-700; }
+.gl-text-red-900 { @include gl-text-red-900; }
+.gl-text-orange-400 { @include gl-text-orange-400; }
+.gl-text-orange-500 { @include gl-text-orange-500; }
+.gl-text-orange-600 { @include gl-text-orange-600; }
.gl-text-orange-700 { @include gl-text-orange-700; }
+.gl-text-green-500 { @include gl-text-green-500; }
.gl-text-green-700 { @include gl-text-green-700; }
.gl-align-items-center { @include gl-align-items-center; }
diff --git a/app/graphql/types/snippet_type.rb b/app/graphql/types/snippet_type.rb
index 7affcae9f8f..4ebdbd5766c 100644
--- a/app/graphql/types/snippet_type.rb
+++ b/app/graphql/types/snippet_type.rb
@@ -67,10 +67,12 @@ module Types
field :ssh_url_to_repo, type: GraphQL::STRING_TYPE,
description: 'SSH URL to the snippet repository',
+ calls_gitaly: true,
null: true
field :http_url_to_repo, type: GraphQL::STRING_TYPE,
description: 'HTTP URL to the snippet repository',
+ calls_gitaly: true,
null: true
markdown_field :description_html, null: true, method: :description
diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb
index 50ce1c67453..f0967b87345 100644
--- a/app/models/project_wiki.rb
+++ b/app/models/project_wiki.rb
@@ -39,6 +39,7 @@ class ProjectWiki
def full_path
@project.full_path + '.wiki'
end
+ alias_method :id, :full_path
# @deprecated use full_path when you need it for an URL route or disk_path when you want to point to the filesystem
alias_method :path_with_namespace, :full_path
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index edf524190e4..973bdc54111 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -310,7 +310,7 @@ class Snippet < ApplicationRecord
end
def versioned_enabled_for?(user)
- repository_exists? && ::Feature.enabled?(:version_snippets, user)
+ ::Feature.enabled?(:version_snippets, user) && repository_exists?
end
class << self
diff --git a/app/models/user.rb b/app/models/user.rb
index 4d450f9305f..343edfae799 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -58,6 +58,8 @@ class User < ApplicationRecord
BLOCKED_MESSAGE = "Your account has been blocked. Please contact your GitLab " \
"administrator if you think this is an error."
+ LOGIN_FORBIDDEN = "Your account does not have the required permission to login. Please contact your GitLab " \
+ "administrator if you think this is an error."
MINIMUM_INACTIVE_DAYS = 180
@@ -299,14 +301,6 @@ class User < ApplicationRecord
def blocked?
true
end
-
- def active_for_authentication?
- false
- end
-
- def inactive_message
- BLOCKED_MESSAGE
- end
end
before_transition do
@@ -354,6 +348,20 @@ class User < ApplicationRecord
.expiring_and_not_notified(at).select(1))
end
+ def active_for_authentication?
+ super && can?(:log_in)
+ end
+
+ def inactive_message
+ if blocked?
+ BLOCKED_MESSAGE
+ elsif internal?
+ LOGIN_FORBIDDEN
+ else
+ super
+ end
+ end
+
def self.with_visible_profile(user)
return with_public_profile if user.nil?
@@ -1701,6 +1709,10 @@ class User < ApplicationRecord
members.non_request.maximum(:access_level)
end
+ def confirmation_required_on_sign_in?
+ !confirmed? && !confirmation_period_valid?
+ end
+
protected
# override, from Devise::Validatable
diff --git a/app/policies/base_policy.rb b/app/policies/base_policy.rb
index ce3e5b0195c..2c26ba565ab 100644
--- a/app/policies/base_policy.rb
+++ b/app/policies/base_policy.rb
@@ -25,8 +25,7 @@ class BasePolicy < DeclarativePolicy::Base
with_options scope: :user, score: 0
condition(:inactive) do
Feature.enabled?(:inactive_policy_condition, default_enabled: true) &&
- @user &&
- !@user&.active_for_authentication?
+ @user&.confirmation_required_on_sign_in? || @user&.access_locked?
end
with_options scope: :user, score: 0
diff --git a/changelogs/unreleased/213136-move-features-to-core-design-management.yml b/changelogs/unreleased/213136-move-features-to-core-design-management.yml
new file mode 100644
index 00000000000..4f66561b0c3
--- /dev/null
+++ b/changelogs/unreleased/213136-move-features-to-core-design-management.yml
@@ -0,0 +1,5 @@
+---
+title: Remove design management as a license feature
+merge_request: 28589
+author:
+type: added
diff --git a/changelogs/unreleased/changelog-spec.yml b/changelogs/unreleased/changelog-spec.yml
new file mode 100644
index 00000000000..dd846b4360f
--- /dev/null
+++ b/changelogs/unreleased/changelog-spec.yml
@@ -0,0 +1,5 @@
+---
+title: Remove duplicate spec from changelog spec
+merge_request: 28801
+author: Rajendra Kadam
+type: added
diff --git a/changelogs/unreleased/feat-x509-signatures-api-endpoint.yml b/changelogs/unreleased/feat-x509-signatures-api-endpoint.yml
new file mode 100644
index 00000000000..54741da3c5f
--- /dev/null
+++ b/changelogs/unreleased/feat-x509-signatures-api-endpoint.yml
@@ -0,0 +1,5 @@
+---
+title: Add api endpoint to get x509 signature
+merge_request: 28590
+author: Roger Meier
+type: added
diff --git a/changelogs/unreleased/jivanvl-replace-refresh-icon-monitoring-dashboard.yml b/changelogs/unreleased/jivanvl-replace-refresh-icon-monitoring-dashboard.yml
new file mode 100644
index 00000000000..1130cceec2d
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-replace-refresh-icon-monitoring-dashboard.yml
@@ -0,0 +1,5 @@
+---
+title: Change redo for retry icon in metrics dashboard
+merge_request: 28670
+author:
+type: other
diff --git a/changelogs/unreleased/vij-snippet-repo-urls-fix.yml b/changelogs/unreleased/vij-snippet-repo-urls-fix.yml
new file mode 100644
index 00000000000..167f0bf5b8e
--- /dev/null
+++ b/changelogs/unreleased/vij-snippet-repo-urls-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Fix GraphQL SnippetType repo urls
+merge_request: 28673
+author:
+type: fixed
diff --git a/doc/api/commits.md b/doc/api/commits.md
index 02fb260d010..356f090f0ff 100644
--- a/doc/api/commits.md
+++ b/doc/api/commits.md
@@ -741,19 +741,43 @@ Parameters:
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/repository/commits/da738facbc19eb2fc2cef57c49be0e6038570352/signature"
```
-Example response if commit is signed:
+Example response if commit is GPG signed:
```json
{
+ "signature_type": "PGP",
+ "verification_status": "verified",
"gpg_key_id": 1,
"gpg_key_primary_keyid": "8254AAB3FBD54AC9",
"gpg_key_user_name": "John Doe",
"gpg_key_user_email": "johndoe@example.com",
- "verification_status": "verified",
"gpg_key_subkey_id": null
}
```
+Example response if commit is x509 signed:
+
+```json
+{
+ "signature_type": "X509",
+ "verification_status": "unverified",
+ "x509_certificate": {
+ "id": 1,
+ "subject": "CN=gitlab@example.org,OU=Example,O=World",
+ "subject_key_identifier": "BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC:BC",
+ "email": "gitlab@example.org",
+ "serial_number": 278969561018901340486471282831158785578,
+ "certificate_status": "good",
+ "x509_issuer": {
+ "id": 1,
+ "subject": "CN=PKI,OU=Example,O=World",
+ "subject_key_identifier": "AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB",
+ "crl_url": "http://example.com/pki.crl"
+ }
+ }
+}
+```
+
Example response if commit is unsigned:
```json
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 1ec4c154039..81b9cd8bece 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -4,7 +4,7 @@ type: reference
# GitLab CI/CD environment variables
-After a brief overview over the use of environment
+After a brief overview of the use of environment
variables, this document teaches you how to use GitLab CI/CD's
variables, presents the full reference for predefined variables,
and dives into more advanced applications.
@@ -715,8 +715,8 @@ if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then
++ CI_SERVER_VERSION_PATCH=0
++ export CI_SERVER_REVISION=f4cc00ae823
++ CI_SERVER_REVISION=f4cc00ae823
-++ export GITLAB_FEATURES=audit_events,burndown_charts,code_owners,contribution_analytics,description_diffs,elastic_search,export_issues,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_board_focus_mode,issue_weights,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,protected_refs_for_users,push_rules,related_issues,repository_mirrors,repository_size_limit,scoped_issue_board,usage_quotas,visual_review_app,wip_limits,adjourned_deletion_for_projects_and_groups,admin_audit_log,auditor_user,batch_comments,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,cluster_deployments,code_analytics,code_owner_approval_required,commit_committer_check,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,custom_prometheus_metrics,cycle_analytics_for_groups,db_load_balancing,default_project_deletion_protection,dependency_proxy,deploy_board,design_management,email_additional_text,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,github_project_service_integration,group_allowed_email_domains,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,merge_trains,metrics_reports,multiple_approval_rules,multiple_clusters,multiple_group_issue_boards,object_storage,operations_dashboard,packages,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,service_desk,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,cluster_health,container_scanning,dast,dependency_scanning,epics,group_ip_restriction,incident_management,insights,license_management,personal_access_token_expiration_policy,pod_logs,prometheus_alerts,pseudonymizer,report_approver_rules,sast,security_dashboard,tracing,web_ide_terminal
-++ GITLAB_FEATURES=audit_events,burndown_charts,code_owners,contribution_analytics,description_diffs,elastic_search,export_issues,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_board_focus_mode,issue_weights,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,protected_refs_for_users,push_rules,related_issues,repository_mirrors,repository_size_limit,scoped_issue_board,usage_quotas,visual_review_app,wip_limits,adjourned_deletion_for_projects_and_groups,admin_audit_log,auditor_user,batch_comments,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,cluster_deployments,code_analytics,code_owner_approval_required,commit_committer_check,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,custom_prometheus_metrics,cycle_analytics_for_groups,db_load_balancing,default_project_deletion_protection,dependency_proxy,deploy_board,design_management,email_additional_text,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,github_project_service_integration,group_allowed_email_domains,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,merge_trains,metrics_reports,multiple_approval_rules,multiple_clusters,multiple_group_issue_boards,object_storage,operations_dashboard,packages,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,service_desk,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,cluster_health,container_scanning,dast,dependency_scanning,epics,group_ip_restriction,incident_management,insights,license_management,personal_access_token_expiration_policy,pod_logs,prometheus_alerts,pseudonymizer,report_approver_rules,sast,security_dashboard,tracing,web_ide_terminal
+++ export GITLAB_FEATURES=audit_events,burndown_charts,code_owners,contribution_analytics,description_diffs,elastic_search,export_issues,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_weights,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,protected_refs_for_users,push_rules,related_issues,repository_mirrors,repository_size_limit,scoped_issue_board,usage_quotas,visual_review_app,wip_limits,adjourned_deletion_for_projects_and_groups,admin_audit_log,auditor_user,batch_comments,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,cluster_deployments,code_analytics,code_owner_approval_required,commit_committer_check,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,custom_prometheus_metrics,cycle_analytics_for_groups,db_load_balancing,default_project_deletion_protection,dependency_proxy,deploy_board,design_management,email_additional_text,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,github_project_service_integration,group_allowed_email_domains,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,merge_trains,metrics_reports,multiple_approval_rules,multiple_clusters,multiple_group_issue_boards,object_storage,operations_dashboard,packages,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,service_desk,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,cluster_health,container_scanning,dast,dependency_scanning,epics,group_ip_restriction,incident_management,insights,license_management,personal_access_token_expiration_policy,pod_logs,prometheus_alerts,pseudonymizer,report_approver_rules,sast,security_dashboard,tracing,web_ide_terminal
+++ GITLAB_FEATURES=audit_events,burndown_charts,code_owners,contribution_analytics,description_diffs,elastic_search,export_issues,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_weights,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,protected_refs_for_users,push_rules,related_issues,repository_mirrors,repository_size_limit,scoped_issue_board,usage_quotas,visual_review_app,wip_limits,adjourned_deletion_for_projects_and_groups,admin_audit_log,auditor_user,batch_comments,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,cluster_deployments,code_analytics,code_owner_approval_required,commit_committer_check,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,custom_prometheus_metrics,cycle_analytics_for_groups,db_load_balancing,default_project_deletion_protection,dependency_proxy,deploy_board,design_management,email_additional_text,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,github_project_service_integration,group_allowed_email_domains,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,merge_trains,metrics_reports,multiple_approval_rules,multiple_clusters,multiple_group_issue_boards,object_storage,operations_dashboard,packages,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,service_desk,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,cluster_health,container_scanning,dast,dependency_scanning,epics,group_ip_restriction,incident_management,insights,license_management,personal_access_token_expiration_policy,pod_logs,prometheus_alerts,pseudonymizer,report_approver_rules,sast,security_dashboard,tracing,web_ide_terminal
++ export CI_PROJECT_ID=17893
++ CI_PROJECT_ID=17893
++ export CI_PROJECT_NAME=ci-debug-trace
diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md
index 141d1db1bf6..429ec262250 100644
--- a/doc/development/testing_guide/frontend_testing.md
+++ b/doc/development/testing_guide/frontend_testing.md
@@ -550,8 +550,9 @@ The more challenging part are mocks, which can be used for functions or even dep
Manual mocks are used to mock modules across the entire Jest environment. This is a very powerful testing tool that helps simplify
unit testing by mocking out modules which cannot be easily consumned in our test environment.
-> NOTE: Do not use manual mocks if a mock should not be consistently applied (i.e. it's only needed by a few specs).
-> Instead, consider using `jest.mock` in the relevant spec file.
+> **WARNING:** Do not use manual mocks if a mock should not be consistently applied in every spec (i.e. it's only needed by a few specs).
+> Instead, consider using [`jest.mock(..)`](https://jestjs.io/docs/en/jest-object#jestmockmodulename-factory-options)
+> (or a similar mocking function) in the relevant spec file.
#### Where should I put manual mocks?
@@ -568,23 +569,27 @@ If a manual mock is needed for a CE module, please place it in `spec/frontend/mo
- We don't support mocking EE modules yet.
- If a mock is found for which a source module doesn't exist, the test suite will fail. 'Virtual' mocks, or mocks that don't have a 1-to-1 association with a source module, are not supported yet.
-### Writing a mock
+#### Manual mock examples
-Create a JS module in the appropriate place in `spec/frontend/mocks/`. That's it. It will automatically mock its source package in all tests.
+- [`mocks/axios_utils`](https://gitlab.com/gitlab-org/gitlab/blob/bd20aeb64c4eed117831556c54b40ff4aee9bfd1/spec/frontend/mocks/ce/lib/utils/axios_utils.js#L1) -
+ This mock is helpful because we don't want any unmocked requests to pass any tests. Also, we are able to inject some test helpers such as `axios.waitForAll`.
+- [`__mocks__/mousetrap/index.js`](https://gitlab.com/gitlab-org/gitlab/blob/cd4c086d894226445be9d18294a060ba46572435/spec/frontend/__mocks__/mousetrap/index.js#L1) -
+ This mock is helpful because the module itself uses amd format which webpack understands, but is incompatible with the jest environment. This mock doesn't remove
+ any behavior, only provides a nice es6 compatible wrapper.
+- [`__mocks__/monaco-editor/index.js`](https://gitlab.com/gitlab-org/gitlab/blob/b7f914cddec9fc5971238cdf12766e79fa1629d7/spec/frontend/__mocks__/monaco-editor/index.js) -
+ This mock is helpful because the monaco package is completely incompatible in a Jest environment. In fact, webpack requires a special loader to make it work. This mock
+ simply makes this package consumable by Jest.
-Make sure that your mock's export has the same format as the mocked module. So, if you're mocking a CommonJS module, you'll need to use `module.exports` instead of the ES6 `export`.
-
-It might be useful for a mock to expose a property that indicates if the mock was loaded. This way, tests can assert the presence of a mock without calling any logic and causing side-effects. The `~/lib/utils/axios_utils` module mock has such a property, `isMock`, that is `true` in the mock and undefined in the original class. Jest's mock functions also have a `mock` property that you can test.
-
-### Bypassing mocks
+### Keep mocks light
-If you ever need to import the original module in your tests, use [`jest.requireActual()`](https://jestjs.io/docs/en/jest-object#jestrequireactualmodulename) (or `jest.requireActual().default` for the default export). The `jest.mock()` and `jest.unmock()` won't have an effect on modules that have a manual mock, because mocks are imported and cached before any tests are run.
+Global mocks introduce magic and technically can reduce test coverage. When mocking is deemed profitable:
-### Keep mocks light
+- Keep the mock short and focused.
+- Please leave a top-level comment in the mock on why it is necessary.
-Global mocks introduce magic and can affect how modules are imported in your tests. Try to keep them as light as possible and dependency-free. A global mock should be useful for any unit test. For example, the `axios_utils` and `jquery` module mocks throw an error when an HTTP request is attempted, since this is useful behaviour in &gt;99% of tests.
+### Additional mocking techniques
-When in doubt, construct mocks in your test file using [`jest.mock()`](https://jestjs.io/docs/en/jest-object#jestmockmodulename-factory-options), [`jest.spyOn()`](https://jestjs.io/docs/en/jest-object#jestspyonobject-methodname), etc.
+Please consult the [official Jest docs](https://jestjs.io/docs/en/jest-object#mock-modules) for a full overview of the available mocking features.
## Running Frontend Tests
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 55f2e3bbd6c..76a33559666 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -57,7 +57,7 @@ The following table depicts the various user permission levels in a project.
| View Dependency list **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
| View License list **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
| View licenses in Dependency list **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
-| View [Design Management](project/issues/design_management.md) pages **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View [Design Management](project/issues/design_management.md) pages | ✓ | ✓ | ✓ | ✓ | ✓ |
| View project code | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
| Pull project code | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
| View GitLab Pages protected by [access control](project/pages/introduction.md#gitlab-pages-access-control-core) | ✓ | ✓ | ✓ | ✓ | ✓ |
@@ -87,7 +87,7 @@ The following table depicts the various user permission levels in a project.
| Create/edit/delete [Releases](project/releases/index.md)| | | ✓ | ✓ | ✓ |
| Pull from [Conan repository](packages/conan_repository/index.md), [Maven repository](packages/maven_repository/index.md), or [NPM registry](packages/npm_registry/index.md) **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
| Publish to [Conan repository](packages/conan_repository/index.md), [Maven repository](packages/maven_repository/index.md), or [NPM registry](packages/npm_registry/index.md) **(PREMIUM)** | | | ✓ | ✓ | ✓ |
-| Upload [Design Management](project/issues/design_management.md) files **(PREMIUM)** | | | ✓ | ✓ | ✓ |
+| Upload [Design Management](project/issues/design_management.md) files | | | ✓ | ✓ | ✓ |
| Create new branches | | | ✓ | ✓ | ✓ |
| Push to non-protected branches | | | ✓ | ✓ | ✓ |
| Force push to non-protected branches | | | ✓ | ✓ | ✓ |
diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md
index 1b9077299d7..2f4f3dd5392 100644
--- a/doc/user/project/issue_board.md
+++ b/doc/user/project/issue_board.md
@@ -203,9 +203,10 @@ If you don't have editing permission in a board, you're still able to see the co
![Viewing board configuration](img/issue_board_view_scope.png)
-### Focus mode **(STARTER)**
+### Focus mode
-> Introduced in [GitLab Starter 9.1](https://about.gitlab.com/releases/2017/04/22/gitlab-9-1-released/#issue-boards-focus-mode-ees-eep).
+> - Introduced in [GitLab Starter 9.1](https://about.gitlab.com/releases/2017/04/22/gitlab-9-1-released/#issue-boards-focus-mode-ees-eep).
+> - Focus mode moved to GitLab Core in GitLab 12.10.
Click the button at the top right to toggle focus mode on and off. In focus mode, the navigation UI is hidden, allowing you to focus on issues in the board.
diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md
index 40771c14ea4..0fbf5ec6f4b 100644
--- a/doc/user/project/issues/design_management.md
+++ b/doc/user/project/issues/design_management.md
@@ -1,4 +1,4 @@
-# Design Management **(PREMIUM)**
+# Design Management
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/660) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.2.
diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md
index af19c7f2b4a..4da65793dbb 100644
--- a/doc/user/project/issues/index.md
+++ b/doc/user/project/issues/index.md
@@ -126,7 +126,7 @@ associated label or assignee will change to match that of the new column. The en
board can also be filtered to only include issues from a certain milestone or an overarching
label.
-### Design Management **(PREMIUM)**
+### Design Management
With [Design Management](design_management.md), you can upload design
assets to issues and view them all together to easily share and
diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md
index 04ad7b30aec..f454144b623 100644
--- a/doc/user/project/settings/import_export.md
+++ b/doc/user/project/settings/import_export.md
@@ -75,7 +75,7 @@ The following items will be exported:
- Project configuration, including services
- Issues with comments, merge requests with diffs and comments, labels, milestones, snippets,
and other project entities
-- Design Management files and data **(PREMIUM)**
+- Design Management files and data
- LFS objects
- Issue boards
- Pipelines history
diff --git a/lib/api/commits.rb b/lib/api/commits.rb
index dfb0066ceb0..086a1b7c402 100644
--- a/lib/api/commits.rb
+++ b/lib/api/commits.rb
@@ -356,7 +356,7 @@ module API
present paginate(commit_merge_requests), with: Entities::MergeRequestBasic
end
- desc "Get a commit's GPG signature" do
+ desc "Get a commit's signature" do
success Entities::CommitSignature
end
params do
@@ -365,11 +365,9 @@ module API
get ':id/repository/commits/:sha/signature', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS do
commit = user_project.commit(params[:sha])
not_found! 'Commit' unless commit
+ not_found! 'Signature' unless commit.has_signature?
- signature = commit.signature
- not_found! 'GPG Signature' unless signature
-
- present signature, with: Entities::CommitSignature
+ present commit, with: Entities::CommitSignature
end
end
end
diff --git a/lib/api/entities/commit_signature.rb b/lib/api/entities/commit_signature.rb
index 8e86d4c1aa6..b5232273521 100644
--- a/lib/api/entities/commit_signature.rb
+++ b/lib/api/entities/commit_signature.rb
@@ -3,10 +3,14 @@
module API
module Entities
class CommitSignature < Grape::Entity
- expose :gpg_key_id
- expose :gpg_key_primary_keyid, :gpg_key_user_name, :gpg_key_user_email
- expose :verification_status
- expose :gpg_key_subkey_id
+ expose :signature_type
+ expose :signature, merge: true do |commit, options|
+ if commit.signature.is_a?(GpgSignature)
+ ::API::Entities::GpgCommitSignature.represent commit.signature, options
+ elsif commit.signature.is_a?(X509CommitSignature)
+ ::API::Entities::X509Signature.represent commit.signature, options
+ end
+ end
end
end
end
diff --git a/lib/api/entities/gpg_commit_signature.rb b/lib/api/entities/gpg_commit_signature.rb
new file mode 100644
index 00000000000..03466452b50
--- /dev/null
+++ b/lib/api/entities/gpg_commit_signature.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class GpgCommitSignature < Grape::Entity
+ expose :verification_status
+ expose :gpg_key_id
+ expose :gpg_key_primary_keyid, :gpg_key_user_name, :gpg_key_user_email
+ expose :gpg_key_subkey_id
+ end
+ end
+end
diff --git a/lib/api/entities/x509_certificate.rb b/lib/api/entities/x509_certificate.rb
new file mode 100644
index 00000000000..aad11339148
--- /dev/null
+++ b/lib/api/entities/x509_certificate.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class X509Certificate < Grape::Entity
+ expose :id
+ expose :subject
+ expose :subject_key_identifier
+ expose :email
+ expose :serial_number
+ expose :certificate_status
+ expose :x509_issuer, using: 'API::Entities::X509Issuer'
+ end
+ end
+end
diff --git a/lib/api/entities/x509_issuer.rb b/lib/api/entities/x509_issuer.rb
new file mode 100644
index 00000000000..b480bc107bc
--- /dev/null
+++ b/lib/api/entities/x509_issuer.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class X509Issuer < Grape::Entity
+ expose :id
+ expose :subject
+ expose :subject_key_identifier
+ expose :crl_url
+ end
+ end
+end
diff --git a/lib/api/entities/x509_signature.rb b/lib/api/entities/x509_signature.rb
new file mode 100644
index 00000000000..909b630288c
--- /dev/null
+++ b/lib/api/entities/x509_signature.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class X509Signature < Grape::Entity
+ expose :verification_status
+ expose :x509_certificate, using: 'API::Entities::X509Certificate'
+ end
+ end
+end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index b9f0e1f7b8b..a56d4cc2e6e 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -11228,9 +11228,6 @@ msgstr ""
msgid "Issue already promoted to epic."
msgstr ""
-msgid "Issue board focus mode"
-msgstr ""
-
msgid "Issue cannot be found."
msgstr ""
@@ -22708,6 +22705,9 @@ msgstr ""
msgid "Vulnerability|Description"
msgstr ""
+msgid "Vulnerability|Evidence"
+msgstr ""
+
msgid "Vulnerability|File"
msgstr ""
diff --git a/package.json b/package.json
index e0c0bf3161b..350d63d9296 100644
--- a/package.json
+++ b/package.json
@@ -39,7 +39,7 @@
"@babel/plugin-syntax-import-meta": "^7.8.3",
"@babel/preset-env": "^7.8.4",
"@gitlab/at.js": "1.5.5",
- "@gitlab/svgs": "1.116.0",
+ "@gitlab/svgs": "1.117.0",
"@gitlab/ui": "11.0.0",
"@gitlab/visual-review-tools": "1.5.1",
"@sentry/browser": "^5.10.2",
diff --git a/spec/controllers/concerns/controller_with_cross_project_access_check_spec.rb b/spec/controllers/concerns/controller_with_cross_project_access_check_spec.rb
index 85989ea3e92..3f9d690837b 100644
--- a/spec/controllers/concerns/controller_with_cross_project_access_check_spec.rb
+++ b/spec/controllers/concerns/controller_with_cross_project_access_check_spec.rb
@@ -14,6 +14,7 @@ describe ControllerWithCrossProjectAccessCheck do
context 'When reading cross project is not allowed' do
before do
allow(Ability).to receive(:allowed).and_call_original
+ expect(Ability).to receive(:allowed?).with(user, :log_in, :global).and_call_original
allow(Ability).to receive(:allowed?)
.with(user, :read_cross_project, :global)
.and_return(false)
diff --git a/spec/controllers/graphql_controller_spec.rb b/spec/controllers/graphql_controller_spec.rb
index a8e78524910..06a949471a7 100644
--- a/spec/controllers/graphql_controller_spec.rb
+++ b/spec/controllers/graphql_controller_spec.rb
@@ -46,6 +46,7 @@ describe GraphqlController do
# User cannot access API in a couple of cases
# * When user is internal(like ghost users)
# * When user is blocked
+ expect(Ability).to receive(:allowed?).with(user, :log_in, :global).and_call_original
expect(Ability).to receive(:allowed?).with(user, :access_api, :global).and_return(false)
post :execute
diff --git a/spec/controllers/groups/boards_controller_spec.rb b/spec/controllers/groups/boards_controller_spec.rb
index acfa8bc9354..b556af0eedc 100644
--- a/spec/controllers/groups/boards_controller_spec.rb
+++ b/spec/controllers/groups/boards_controller_spec.rb
@@ -26,6 +26,7 @@ describe Groups::BoardsController do
context 'with unauthorized user' do
before do
+ expect(Ability).to receive(:allowed?).with(user, :log_in, :global).and_call_original
allow(Ability).to receive(:allowed?).with(user, :read_cross_project, :global).and_return(true)
allow(Ability).to receive(:allowed?).with(user, :read_group, group).and_return(true)
allow(Ability).to receive(:allowed?).with(user, :read_board, group).and_return(false)
@@ -70,6 +71,7 @@ describe Groups::BoardsController do
context 'with unauthorized user' do
before do
+ expect(Ability).to receive(:allowed?).with(user, :log_in, :global).and_call_original
allow(Ability).to receive(:allowed?).with(user, :read_cross_project, :global).and_return(true)
allow(Ability).to receive(:allowed?).with(user, :read_group, group).and_return(true)
allow(Ability).to receive(:allowed?).with(user, :read_board, group).and_return(false)
@@ -106,6 +108,7 @@ describe Groups::BoardsController do
context 'with unauthorized user' do
before do
+ expect(Ability).to receive(:allowed?).with(user, :log_in, :global).and_call_original
allow(Ability).to receive(:allowed?).with(user, :read_cross_project, :global).and_return(true)
allow(Ability).to receive(:allowed?).with(user, :read_group, group).and_return(true)
allow(Ability).to receive(:allowed?).with(user, :read_board, group).and_return(false)
@@ -144,6 +147,7 @@ describe Groups::BoardsController do
context 'with unauthorized user' do
before do
+ expect(Ability).to receive(:allowed?).with(user, :log_in, :global).and_call_original
allow(Ability).to receive(:allowed?).with(user, :read_cross_project, :global).and_return(true)
allow(Ability).to receive(:allowed?).with(user, :read_group, group).and_return(true)
allow(Ability).to receive(:allowed?).with(user, :read_group, group).and_return(false)
diff --git a/spec/controllers/projects/boards_controller_spec.rb b/spec/controllers/projects/boards_controller_spec.rb
index ebfdb997974..6634801939b 100644
--- a/spec/controllers/projects/boards_controller_spec.rb
+++ b/spec/controllers/projects/boards_controller_spec.rb
@@ -32,6 +32,7 @@ describe Projects::BoardsController do
context 'with unauthorized user' do
before do
+ expect(Ability).to receive(:allowed?).with(user, :log_in, :global).and_call_original
allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true)
allow(Ability).to receive(:allowed?).with(user, :read_board, project).and_return(false)
end
@@ -75,6 +76,7 @@ describe Projects::BoardsController do
context 'with unauthorized user' do
before do
+ expect(Ability).to receive(:allowed?).with(user, :log_in, :global).and_call_original
allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true)
allow(Ability).to receive(:allowed?).with(user, :read_board, project).and_return(false)
end
@@ -130,6 +132,7 @@ describe Projects::BoardsController do
context 'with unauthorized user' do
before do
+ expect(Ability).to receive(:allowed?).with(user, :log_in, :global).and_call_original
allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true)
allow(Ability).to receive(:allowed?).with(user, :read_board, project).and_return(false)
end
@@ -167,6 +170,7 @@ describe Projects::BoardsController do
context 'with unauthorized user' do
before do
+ expect(Ability).to receive(:allowed?).with(user, :log_in, :global).and_call_original
allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true)
allow(Ability).to receive(:allowed?).with(user, :read_board, project).and_return(false)
end
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index ccaf0dd997b..fb3c163dff1 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -29,6 +29,7 @@ FactoryBot.define do
end
pipeline factory: :ci_pipeline
+ project { pipeline.project }
trait :degenerated do
options { nil }
@@ -220,10 +221,6 @@ FactoryBot.define do
end
end
- after(:build) do |build, evaluator|
- build.project ||= build.pipeline.project
- end
-
trait :with_deployment do
after(:build) do |build, evaluator|
##
diff --git a/spec/factories/internal_ids.rb b/spec/factories/internal_ids.rb
index bc6ea41ec06..02baaedb996 100644
--- a/spec/factories/internal_ids.rb
+++ b/spec/factories/internal_ids.rb
@@ -6,4 +6,10 @@ FactoryBot.define do
usage { :issues }
last_value { project.issues.maximum(:iid) || 0 }
end
+
+ trait :has_internal_id do
+ after(:stub) do |record|
+ record.iid ||= generate(:iid)
+ end
+ end
end
diff --git a/spec/factories/issues.rb b/spec/factories/issues.rb
index 24c12a66599..4d0924a9412 100644
--- a/spec/factories/issues.rb
+++ b/spec/factories/issues.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
FactoryBot.define do
- factory :issue do
+ factory :issue, traits: [:has_internal_id] do
title { generate(:title) }
project
author { project.creator }
diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb
index 08a8ede61b1..abccd775c8a 100644
--- a/spec/factories/merge_requests.rb
+++ b/spec/factories/merge_requests.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
FactoryBot.define do
- factory :merge_request do
+ factory :merge_request, traits: [:has_internal_id] do
title { generate(:title) }
association :source_project, :repository, factory: :project
target_project { source_project }
diff --git a/spec/factories/milestones.rb b/spec/factories/milestones.rb
index 32eee645f6a..151d286cc29 100644
--- a/spec/factories/milestones.rb
+++ b/spec/factories/milestones.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
FactoryBot.define do
- factory :milestone do
+ factory :milestone, traits: [:has_internal_id] do
title
transient do
diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb
index a15c7625500..fdd1a9a18b2 100644
--- a/spec/factories/notes.rb
+++ b/spec/factories/notes.rb
@@ -40,7 +40,7 @@ FactoryBot.define do
factory :discussion_note_on_personal_snippet, traits: [:on_personal_snippet], class: 'DiscussionNote'
- factory :discussion_note_on_snippet, traits: [:on_snippet], class: 'DiscussionNote'
+ factory :discussion_note_on_project_snippet, traits: [:on_project_snippet], class: 'DiscussionNote'
factory :legacy_diff_note_on_commit, traits: [:on_commit, :legacy_diff_note], class: 'LegacyDiffNote'
@@ -120,23 +120,19 @@ FactoryBot.define do
end
trait :on_issue do
- noteable { create(:issue, project: project) }
- end
-
- trait :on_snippet do
- noteable { create(:snippet, project: project) }
+ noteable { association(:issue, project: project) }
end
trait :on_merge_request do
- noteable { create(:merge_request, source_project: project) }
+ noteable { association(:merge_request, source_project: project) }
end
trait :on_project_snippet do
- noteable { create(:project_snippet, project: project) }
+ noteable { association(:project_snippet, project: project) }
end
trait :on_personal_snippet do
- noteable { create(:personal_snippet) }
+ noteable { association(:personal_snippet) }
project { nil }
end
diff --git a/spec/factories/sequences.rb b/spec/factories/sequences.rb
index 17b54d69372..cdc64a8502e 100644
--- a/spec/factories/sequences.rb
+++ b/spec/factories/sequences.rb
@@ -11,4 +11,5 @@ FactoryBot.define do
sequence(:label_title) { |n| "label#{n}" }
sequence(:branch) { |n| "my-branch-#{n}" }
sequence(:past_time) { |n| 4.hours.ago + (2 * n).seconds }
+ sequence(:iid)
end
diff --git a/spec/frontend/fixtures/snippet.rb b/spec/frontend/fixtures/snippet.rb
index e91050cd2c5..d27c2fbe68b 100644
--- a/spec/frontend/fixtures/snippet.rb
+++ b/spec/frontend/fixtures/snippet.rb
@@ -27,7 +27,7 @@ describe SnippetsController, '(JavaScript fixtures)', type: :controller do
end
it 'snippets/show.html' do
- create(:discussion_note_on_snippet, noteable: snippet, project: project, author: admin, note: '- [ ] Task List Item')
+ create(:discussion_note_on_project_snippet, noteable: snippet, project: project, author: admin, note: '- [ ] Task List Item')
get(:show, params: { id: snippet.to_param })
diff --git a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
index f7e15d4a5c4..88710b23bc9 100644
--- a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
+++ b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
@@ -96,7 +96,7 @@ exports[`Dashboard template matches the default snapshot 1`] = `
variant="default"
>
<icon-stub
- name="repeat"
+ name="retry"
size="16"
/>
</gl-deprecated-button-stub>
diff --git a/spec/graphql/types/snippet_type_spec.rb b/spec/graphql/types/snippet_type_spec.rb
index ba0152ae983..6e580711fda 100644
--- a/spec/graphql/types/snippet_type_spec.rb
+++ b/spec/graphql/types/snippet_type_spec.rb
@@ -27,25 +27,9 @@ describe GitlabSchema.types['Snippet'] do
end
end
- describe 'Repository URLs' do
- let(:query) do
- %(
- {
- snippets {
- nodes {
- sshUrlToRepo
- httpUrlToRepo
- }
- }
- }
- )
- end
- let(:response) { subject.dig('data', 'snippets', 'nodes')[0] }
-
- subject { GitlabSchema.execute(query, context: { current_user: user }).as_json }
-
+ shared_examples 'snippets with repositories' do
context 'when snippet has repository' do
- let!(:snippet) { create(:personal_snippet, :repository, :public, author: user) }
+ let_it_be(:snippet) { create(:personal_snippet, :repository, :public, author: user) }
it 'responds with repository URLs' do
expect(response['sshUrlToRepo']).to eq(snippet.ssh_url_to_repo)
@@ -60,14 +44,44 @@ describe GitlabSchema.types['Snippet'] do
it_behaves_like 'response without repository URLs'
end
end
+ end
+ shared_examples 'snippets without repositories' do
context 'when snippet does not have a repository' do
- let!(:snippet) { create(:personal_snippet, :public, author: user) }
+ let_it_be(:snippet) { create(:personal_snippet, :public, author: user) }
it_behaves_like 'response without repository URLs'
end
end
+ describe 'Repository URLs' do
+ let(:query) do
+ %(
+ {
+ snippets {
+ nodes {
+ sshUrlToRepo
+ httpUrlToRepo
+ }
+ }
+ }
+ )
+ end
+ let(:response) { subject.dig('data', 'snippets', 'nodes')[0] }
+
+ subject { GitlabSchema.execute(query, context: { current_user: user }).as_json }
+
+ context 'when RequestStore is disabled' do
+ it_behaves_like 'snippets with repositories'
+ it_behaves_like 'snippets without repositories'
+ end
+
+ context 'when RequestStore is enabled', :request_store do
+ it_behaves_like 'snippets with repositories'
+ it_behaves_like 'snippets without repositories'
+ end
+ end
+
describe '#blob' do
let(:query_blob) { subject.dig('data', 'snippets', 'edges')[0]['node']['blob'] }
let(:query) do
diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb
index 0109525bcac..ff99f76eb4d 100644
--- a/spec/helpers/events_helper_spec.rb
+++ b/spec/helpers/events_helper_spec.rb
@@ -181,7 +181,7 @@ describe EventsHelper do
end
it 'returns a project snippet note url' do
- event.target = create(:note, :on_snippet, note: 'keep going')
+ event.target = create(:note_on_project_snippet, note: 'keep going')
expect(subject).to eq("#{project_base_url}/snippets/#{event.note_target.id}#note_#{event.target.id}")
end
diff --git a/spec/lib/gitlab/danger/changelog_spec.rb b/spec/lib/gitlab/danger/changelog_spec.rb
index c61e47f80d9..ba23c3828de 100644
--- a/spec/lib/gitlab/danger/changelog_spec.rb
+++ b/spec/lib/gitlab/danger/changelog_spec.rb
@@ -28,18 +28,6 @@ describe Gitlab::Danger::Changelog do
describe '#needed?' do
subject { changelog.needed? }
- [
- { docs: nil },
- { none: nil },
- { docs: nil, none: nil }
- ].each do |categories|
- let(:changes_by_category) { categories }
-
- it "is falsy when categories don't require a changelog" do
- is_expected.to be_falsy
- end
- end
-
where(:categories, :labels) do
{ backend: nil } | %w[backend backstage]
{ frontend: nil, docs: nil } | ['ci-build']
@@ -50,7 +38,7 @@ describe Gitlab::Danger::Changelog do
let(:changes_by_category) { categories }
let(:mr_labels) { labels }
- it "is falsy when labels require no changelog" do
+ it "is falsy when categories and labels require no changelog" do
is_expected.to be_falsy
end
end
diff --git a/spec/lib/gitlab/gfm/reference_rewriter_spec.rb b/spec/lib/gitlab/gfm/reference_rewriter_spec.rb
index a3904f4a97c..084dde1f93f 100644
--- a/spec/lib/gitlab/gfm/reference_rewriter_spec.rb
+++ b/spec/lib/gitlab/gfm/reference_rewriter_spec.rb
@@ -3,11 +3,11 @@
require 'spec_helper'
describe Gitlab::Gfm::ReferenceRewriter do
- let(:group) { create(:group) }
- let(:old_project) { create(:project, name: 'old-project', group: group) }
- let(:new_project) { create(:project, name: 'new-project', group: group) }
- let(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:user) { create(:user) }
+ let(:new_project) { create(:project, name: 'new-project', group: group) }
+ let(:old_project) { create(:project, name: 'old-project', group: group) }
let(:old_project_ref) { old_project.to_reference_base(new_project) }
let(:text) { 'some text' }
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 291c628bfde..12f83e6d8c6 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -4475,4 +4475,73 @@ describe User, :do_not_mock_admin_mode do
end
end
end
+
+ describe '#active_for_authentication?' do
+ subject { user.active_for_authentication? }
+
+ let(:user) { create(:user) }
+
+ context 'when user is blocked' do
+ before do
+ user.block
+ end
+
+ it { is_expected.to be false }
+ end
+
+ context 'when user is a ghost user' do
+ before do
+ user.update(ghost: true)
+ end
+
+ it { is_expected.to be false }
+ end
+
+ context 'based on user type' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:user_type, :expected_result) do
+ 'human' | true
+ 'alert_bot' | false
+ end
+
+ with_them do
+ before do
+ user.update(user_type: user_type)
+ end
+
+ it { is_expected.to be expected_result }
+ end
+ end
+ end
+
+ describe '#inactive_message' do
+ subject { user.inactive_message }
+
+ let(:user) { create(:user) }
+
+ context 'when user is blocked' do
+ before do
+ user.block
+ end
+
+ it { is_expected.to eq User::BLOCKED_MESSAGE }
+ end
+
+ context 'when user is an internal user' do
+ before do
+ user.update(ghost: true)
+ end
+
+ it { is_expected.to be User::LOGIN_FORBIDDEN }
+ end
+
+ context 'when user is locked' do
+ before do
+ user.lock_access!
+ end
+
+ it { is_expected.to be :locked }
+ end
+ end
end
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index 4b110874df0..86b3dd4095f 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -1889,11 +1889,11 @@ describe API::Commits do
context 'unsigned commit' do
it_behaves_like '404 response' do
let(:request) { get api(route, current_user) }
- let(:message) { '404 GPG Signature Not Found'}
+ let(:message) { '404 Signature Not Found'}
end
end
- context 'signed commit' do
+ context 'gpg signed commit' do
let(:commit) { project.repository.commit(GpgHelpers::SIGNED_COMMIT_SHA) }
let(:commit_id) { commit.id }
@@ -1901,11 +1901,35 @@ describe API::Commits do
get api(route, current_user)
expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['signature_type']).to eq('PGP')
expect(json_response['gpg_key_id']).to eq(commit.signature.gpg_key_id)
expect(json_response['gpg_key_subkey_id']).to eq(commit.signature.gpg_key_subkey_id)
expect(json_response['gpg_key_primary_keyid']).to eq(commit.signature.gpg_key_primary_keyid)
expect(json_response['verification_status']).to eq(commit.signature.verification_status)
end
end
+
+ context 'x509 signed commit' do
+ let(:commit) { project.repository.commit_by(oid: '189a6c924013fc3fe40d6f1ec1dc20214183bc97') }
+ let(:commit_id) { commit.id }
+
+ it 'returns correct JSON' do
+ get api(route, current_user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['signature_type']).to eq('X509')
+ expect(json_response['verification_status']).to eq(commit.signature.verification_status)
+ expect(json_response['x509_certificate']['id']).to eq(commit.signature.x509_certificate.id)
+ expect(json_response['x509_certificate']['subject']).to eq(commit.signature.x509_certificate.subject)
+ expect(json_response['x509_certificate']['subject_key_identifier']).to eq(commit.signature.x509_certificate.subject_key_identifier)
+ expect(json_response['x509_certificate']['email']).to eq(commit.signature.x509_certificate.email)
+ expect(json_response['x509_certificate']['serial_number']).to eq(commit.signature.x509_certificate.serial_number)
+ expect(json_response['x509_certificate']['certificate_status']).to eq(commit.signature.x509_certificate.certificate_status)
+ expect(json_response['x509_certificate']['x509_issuer']['id']).to eq(commit.signature.x509_certificate.x509_issuer.id)
+ expect(json_response['x509_certificate']['x509_issuer']['subject']).to eq(commit.signature.x509_certificate.x509_issuer.subject)
+ expect(json_response['x509_certificate']['x509_issuer']['subject_key_identifier']).to eq(commit.signature.x509_certificate.x509_issuer.subject_key_identifier)
+ expect(json_response['x509_certificate']['x509_issuer']['crl_url']).to eq(commit.signature.x509_certificate.x509_issuer.crl_url)
+ end
+ end
end
end
diff --git a/spec/requests/api/discussions_spec.rb b/spec/requests/api/discussions_spec.rb
index e4dd6dfbeff..cb3efb2cf5f 100644
--- a/spec/requests/api/discussions_spec.rb
+++ b/spec/requests/api/discussions_spec.rb
@@ -31,7 +31,7 @@ describe API::Discussions do
context 'when noteable is a Snippet' do
let!(:snippet) { create(:project_snippet, project: project, author: user) }
- let!(:snippet_note) { create(:discussion_note_on_snippet, noteable: snippet, project: project, author: user) }
+ let!(:snippet_note) { create(:discussion_note_on_project_snippet, noteable: snippet, project: project, author: user) }
it_behaves_like 'discussions API', 'projects', 'snippets', 'id' do
let(:parent) { project }
diff --git a/spec/support/helpers/repo_helpers.rb b/spec/support/helpers/repo_helpers.rb
index 255a15b1ab0..7741c805b37 100644
--- a/spec/support/helpers/repo_helpers.rb
+++ b/spec/support/helpers/repo_helpers.rb
@@ -33,6 +33,7 @@ eos
def sample_commit
OpenStruct.new(
id: "570e7b2abdd848b95f2f578043fc23bd6f6fd24d",
+ sha: "570e7b2abdd848b95f2f578043fc23bd6f6fd24d",
parent_id: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9',
author_full_name: "Dmitriy Zaporozhets",
author_email: "dmitriy.zaporozhets@gmail.com",
@@ -50,6 +51,7 @@ eos
def another_sample_commit
OpenStruct.new(
id: "e56497bb5f03a90a51293fc6d516788730953899",
+ sha: "e56497bb5f03a90a51293fc6d516788730953899",
parent_id: '4cd80ccab63c82b4bad16faa5193fbd2aa06df40',
author_full_name: "Sytse Sijbrandij",
author_email: "sytse@gitlab.com",
@@ -69,6 +71,7 @@ eos
def sample_big_commit
OpenStruct.new(
id: "913c66a37b4a45b9769037c55c2d238bd0942d2e",
+ sha: "913c66a37b4a45b9769037c55c2d238bd0942d2e",
author_full_name: "Dmitriy Zaporozhets",
author_email: "dmitriy.zaporozhets@gmail.com",
message: <<eos
@@ -81,6 +84,7 @@ eos
def sample_image_commit
OpenStruct.new(
id: "2f63565e7aac07bcdadb654e253078b727143ec4",
+ sha: "2f63565e7aac07bcdadb654e253078b727143ec4",
author_full_name: "Dmitriy Zaporozhets",
author_email: "dmitriy.zaporozhets@gmail.com",
old_blob_id: '33f3729a45c02fc67d00adb1b8bca394b0e761d9',
diff --git a/yarn.lock b/yarn.lock
index 2c0afb67e8d..2a75187b06a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -781,10 +781,10 @@
eslint-plugin-vue "^6.2.1"
vue-eslint-parser "^7.0.0"
-"@gitlab/svgs@1.116.0":
- version "1.116.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.116.0.tgz#a3c89f950bb256c2e109444c9a85fecdd261292c"
- integrity sha512-sZLn3acu0IyrSnZRU1rE3UjxF6FlwvBNfjKQgn0qclxdbe8Ya6cGNVq4aGdCEkHwvb9rFpKbfHBujVgVKNkxSA==
+"@gitlab/svgs@1.117.0":
+ version "1.117.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.117.0.tgz#05239ddcf529c62ca29e1ec1a25a7e24efb98207"
+ integrity sha512-dGy/VWuRAFCTZX3Yqu1+RnAHTSUWafteIk/RMfUCN9B/EMbYzjhYsNy0NLVoZ23Rj/KGv1bUGHvyQCoPP6VzpA==
"@gitlab/ui@11.0.0":
version "11.0.0"