Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-03-23 03:07:30 +00:00
parent 1b6de87b5c
commit 5316a9bca9
53 changed files with 681 additions and 199 deletions

View file

@ -215,18 +215,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/administration/audit_events.md @eread /doc/administration/audit_events.md @eread
/doc/administration/audit_reports.md @eread /doc/administration/audit_reports.md @eread
/doc/administration/auditor_users.md @axil /doc/administration/auditor_users.md @axil
/doc/administration/auth/atlassian.md @eread /doc/administration/auth/ @eread
/doc/administration/auth/authentiq.md @eread
/doc/administration/auth/cognito.md @eread
/doc/administration/auth/crowd.md @eread
/doc/administration/auth/index.md @eread
/doc/administration/auth/ldap/google_secure_ldap.md @eread
/doc/administration/auth/jwt.md @eread
/doc/administration/auth/ldap/ldap-troubleshooting.md @eread
/doc/administration/auth/ldap/ldap_synchronization.md @eread
/doc/administration/auth/ldap/index.md @eread
/doc/administration/auth/oidc.md @eread
/doc/administration/auth/smartcard.md @eread
/doc/administration/cicd.md @marcel.amirault /doc/administration/cicd.md @marcel.amirault
/doc/administration/clusters/kas.md @sselhorn /doc/administration/clusters/kas.md @sselhorn
/doc/administration/compliance.md @eread /doc/administration/compliance.md @eread
@ -269,8 +258,8 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/administration/operations/sidekiq_memory_killer.md @marcel.amirault /doc/administration/operations/sidekiq_memory_killer.md @marcel.amirault
/doc/administration/package_information/ @axil /doc/administration/package_information/ @axil
/doc/administration/packages/ @ngaskill /doc/administration/packages/ @ngaskill
/doc/administration/pages/index.md @rdickenson /doc/administration/pages/index.md @aqualls
/doc/administration/pages/source.md @rdickenson /doc/administration/pages/source.md @aqualls
/doc/administration/polling.md @axil /doc/administration/polling.md @axil
/doc/administration/postgresql/ @aqualls /doc/administration/postgresql/ @aqualls
/doc/administration/pseudonymizer.md @axil /doc/administration/pseudonymizer.md @axil
@ -291,6 +280,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/administration/smime_signing_email.md @axil /doc/administration/smime_signing_email.md @axil
/doc/administration/snippets/index.md @aqualls /doc/administration/snippets/index.md @aqualls
/doc/administration/static_objects_external_storage.md @aqualls /doc/administration/static_objects_external_storage.md @aqualls
/doc/administration/system_hooks.md @kpaizee
/doc/administration/terraform_state.md @sselhorn /doc/administration/terraform_state.md @sselhorn
/doc/administration/timezone.md @axil /doc/administration/timezone.md @axil
/doc/administration/troubleshooting/ @axil /doc/administration/troubleshooting/ @axil
@ -340,6 +330,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/api/graphql/ @kpaizee /doc/api/graphql/ @kpaizee
/doc/api/graphql/custom_emoji.md @msedlakjakubowski /doc/api/graphql/custom_emoji.md @msedlakjakubowski
/doc/api/graphql/sample_issue_boards.md @msedlakjakubowski /doc/api/graphql/sample_issue_boards.md @msedlakjakubowski
/doc/api/group_access_tokens.md @eread
/doc/api/group_activity_analytics.md @fneill /doc/api/group_activity_analytics.md @fneill
/doc/api/group_badges.md @eread /doc/api/group_badges.md @eread
/doc/api/group_boards.md @msedlakjakubowski /doc/api/group_boards.md @msedlakjakubowski
@ -369,6 +360,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/api/keys.md @aqualls /doc/api/keys.md @aqualls
/doc/api/labels.md @msedlakjakubowski /doc/api/labels.md @msedlakjakubowski
/doc/api/license.md @kpaizee /doc/api/license.md @kpaizee
/doc/api/linked_epics.md @msedlakjakubowski
/doc/api/lint.md @marcel.amirault /doc/api/lint.md @marcel.amirault
/doc/api/managed_licenses.md @kpaizee /doc/api/managed_licenses.md @kpaizee
/doc/api/markdown.md @aqualls /doc/api/markdown.md @aqualls
@ -387,13 +379,15 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/api/openapi/openapi_interactive.md @kpaizee /doc/api/openapi/openapi_interactive.md @kpaizee
/doc/api/packages.md @ngaskill /doc/api/packages.md @ngaskill
/doc/api/packages/ @ngaskill /doc/api/packages/ @ngaskill
/doc/api/pages_domains.md @rdickenson /doc/api/pages_domains.md @aqualls
/doc/api/pages.md @rdickenson /doc/api/pages.md @aqualls
/doc/api/personal_access_tokens.md @eread /doc/api/personal_access_tokens.md @eread
/doc/api/pipeline_schedules.md @marcel.amirault /doc/api/pipeline_schedules.md @marcel.amirault
/doc/api/pipeline_triggers.md @marcel.amirault /doc/api/pipeline_triggers.md @marcel.amirault
/doc/api/pipelines.md @marcel.amirault /doc/api/pipelines.md @marcel.amirault
/doc/api/scim.md @eread
/doc/api/plan_limits.md @eread /doc/api/plan_limits.md @eread
/doc/api/project_access_tokens.md @eread
/doc/api/project_aliases.md @aqualls /doc/api/project_aliases.md @aqualls
/doc/api/project_badges.md @aqualls /doc/api/project_badges.md @aqualls
/doc/api/project_clusters.md @sselhorn /doc/api/project_clusters.md @sselhorn
@ -422,7 +416,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/api/resource_state_events.md @msedlakjakubowski /doc/api/resource_state_events.md @msedlakjakubowski
/doc/api/resource_weight_events.md @msedlakjakubowski /doc/api/resource_weight_events.md @msedlakjakubowski
/doc/api/runners.md @sselhorn /doc/api/runners.md @sselhorn
/doc/api/scim.md @eread /doc/api/plan_limits.md @eread
/doc/api/search.md @aqualls /doc/api/search.md @aqualls
/doc/api/secure_files.md @marcel.amirault /doc/api/secure_files.md @marcel.amirault
/doc/api/settings.md @eread /doc/api/settings.md @eread
@ -509,6 +503,8 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/auto_devops.md @sselhorn /doc/development/auto_devops.md @sselhorn
/doc/development/avoiding_downtime_in_migrations.md @aqualls /doc/development/avoiding_downtime_in_migrations.md @aqualls
/doc/development/backend/create_source_code_be/index.md @aqualls /doc/development/backend/create_source_code_be/index.md @aqualls
/doc/development/backend/ruby_style_guide.md @marcia
/doc/development/background_migrations.md @marcia
/doc/development/build_test_package.md @axil /doc/development/build_test_package.md @axil
/doc/development/bulk_import.md @ngaskill /doc/development/bulk_import.md @ngaskill
/doc/development/cascading_settings.md @eread /doc/development/cascading_settings.md @eread
@ -518,11 +514,15 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/cicd/schema.md @marcel.amirault /doc/development/cicd/schema.md @marcel.amirault
/doc/development/cicd/templates.md @marcel.amirault /doc/development/cicd/templates.md @marcel.amirault
/doc/development/code_intelligence/index.md @aqualls /doc/development/code_intelligence/index.md @aqualls
/doc/development/contributing/ @marcia
/doc/development/contributing/merge_request_workflow.md @aqualls
/doc/development/creating_enums.md @aqualls /doc/development/creating_enums.md @aqualls
/doc/development/database_debugging.md @aqualls /doc/development/database_debugging.md @aqualls
/doc/development/database_query_comments.md @aqualls /doc/development/database_query_comments.md @aqualls
/doc/development/database_review.md @aqualls /doc/development/database_review.md @aqualls
/doc/development/database/client_side_connection_pool.md @marcia
/doc/development/database/ @aqualls /doc/development/database/ @aqualls
/doc/development/database/multiple_databases.md @marcia
/doc/development/db_dump.md @aqualls /doc/development/db_dump.md @aqualls
/doc/development/developing_with_solargraph.md @aqualls /doc/development/developing_with_solargraph.md @aqualls
/doc/development/distributed_tracing.md @ngaskill /doc/development/distributed_tracing.md @ngaskill
@ -538,7 +538,12 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/experiment_guide/ @kpaizee /doc/development/experiment_guide/ @kpaizee
/doc/development/export_csv.md @ngaskill /doc/development/export_csv.md @ngaskill
/doc/development/fe_guide/content_editor.md @aqualls /doc/development/fe_guide/content_editor.md @aqualls
/doc/development/fe_guide/dark_mode.md @marcia
/doc/development/fe_guide/graphql.md @marcia
/doc/development/fe_guide/source_editor.md @aqualls /doc/development/fe_guide/source_editor.md @aqualls
/doc/development/feature_categorization/index.md @marcia
/doc/development/feature_flags/controls.md @marcia
/doc/development/feature_flags/index.md @marcia
/doc/development/filtering_by_label.md @msedlakjakubowski /doc/development/filtering_by_label.md @msedlakjakubowski
/doc/development/foreign_keys.md @aqualls /doc/development/foreign_keys.md @aqualls
/doc/development/geo.md @axil /doc/development/geo.md @axil
@ -551,12 +556,15 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/i18n/ @ngaskill /doc/development/i18n/ @ngaskill
/doc/development/image_scaling.md @marcel.amirault /doc/development/image_scaling.md @marcel.amirault
/doc/development/import_export.md @ngaskill /doc/development/import_export.md @ngaskill
/doc/development/index.md @marcia
/doc/development/insert_into_tables_in_batches.md @aqualls /doc/development/insert_into_tables_in_batches.md @aqualls
/doc/development/integrations/jenkins.md @kpaizee /doc/development/integrations/ @kpaizee
/doc/development/integrations/codesandbox.md @marcia
/doc/development/integrations/jira_connect.md @kpaizee /doc/development/integrations/jira_connect.md @kpaizee
/doc/development/integrations/secure_partner_integration.md @rdickenson /doc/development/integrations/secure_partner_integration.md @rdickenson
/doc/development/integrations/secure.md @ngaskill /doc/development/integrations/secure.md @ngaskill
/doc/development/internal_api/ @aqualls /doc/development/internal_api/ @aqualls
/doc/development/internal_users.md @marcia
/doc/development/issuable-like-models.md @msedlakjakubowski /doc/development/issuable-like-models.md @msedlakjakubowski
/doc/development/issue_types.md @msedlakjakubowski /doc/development/issue_types.md @msedlakjakubowski
/doc/development/iterating_tables_in_batches.md @aqualls /doc/development/iterating_tables_in_batches.md @aqualls
@ -565,17 +573,24 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/licensed_feature_availability.md @sselhorn /doc/development/licensed_feature_availability.md @sselhorn
/doc/development/maintenance_mode.md @axil /doc/development/maintenance_mode.md @axil
/doc/development/new_fe_guide/modules/widget_extensions.md @aqualls /doc/development/new_fe_guide/modules/widget_extensions.md @aqualls
/doc/development/new_fe_guide/tips.md @marcia
/doc/development/omnibus.md @axil /doc/development/omnibus.md @axil
/doc/development/ordering_table_columns.md @aqualls /doc/development/ordering_table_columns.md @aqualls
/doc/development/packages.md @ngaskill /doc/development/packages.md @ngaskill
/doc/development/permissions.md @eread
/doc/development/policies.md @eread
/doc/development/product_qualified_lead_guide/index.md @kpaizee /doc/development/product_qualified_lead_guide/index.md @kpaizee
/doc/development/query_performance.md @aqualls /doc/development/query_performance.md @aqualls
/doc/development/real_time.md @msedlakjakubowski /doc/development/real_time.md @msedlakjakubowski
/doc/development/secure_coding_guidelines.md @marcia
/doc/development/serializing_data.md @aqualls /doc/development/serializing_data.md @aqualls
/doc/development/service_ping/ @fneill /doc/development/service_ping/ @fneill
/doc/development/snowplow/ @fneill /doc/development/snowplow/ @fneill
/doc/development/spam_protection_and_captcha/ @eread
/doc/development/sql.md @aqualls /doc/development/sql.md @aqualls
/doc/development/swapping_tables.md @aqualls /doc/development/swapping_tables.md @aqualls
/doc/development/testing_guide/best_practices.md @marcia
/doc/development/testing_guide/end_to_end/best_practices.md @marcia
/doc/development/understanding_explain_plans.md @aqualls /doc/development/understanding_explain_plans.md @aqualls
/doc/development/value_stream_analytics.md @fneill /doc/development/value_stream_analytics.md @fneill
/doc/development/value_stream_analytics/value_stream_analytics_aggregated_backend.md @fneill /doc/development/value_stream_analytics/value_stream_analytics_aggregated_backend.md @fneill
@ -583,6 +598,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/wikis.md @aqualls /doc/development/wikis.md @aqualls
/doc/development/work_items.md @msedlakjakubowski /doc/development/work_items.md @msedlakjakubowski
/doc/development/work_items_widgets.md @msedlakjakubowski /doc/development/work_items_widgets.md @msedlakjakubowski
/doc/development/workspace/index.md @marcia
/doc/downgrade_ee_to_ce/index.md @axil /doc/downgrade_ee_to_ce/index.md @axil
/doc/gitlab-basics/add-file.md @aqualls /doc/gitlab-basics/add-file.md @aqualls
/doc/gitlab-basics/command-line-commands.md @aqualls /doc/gitlab-basics/command-line-commands.md @aqualls
@ -610,6 +626,8 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/raketasks/generate_sample_prometheus_data.md @ngaskill /doc/raketasks/generate_sample_prometheus_data.md @ngaskill
/doc/raketasks/migrate_snippets.md @aqualls /doc/raketasks/migrate_snippets.md @aqualls
/doc/raketasks/spdx.md @rdickenson /doc/raketasks/spdx.md @rdickenson
/doc/raketasks/user_management.md @axil
/doc/raketasks/web_hooks.md @axil
/doc/raketasks/x509_signatures.md @aqualls /doc/raketasks/x509_signatures.md @aqualls
/doc/security/ @eread /doc/security/ @eread
/doc/ssh/index.md @eread /doc/ssh/index.md @eread
@ -632,6 +650,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/user/admin_area/geo_nodes.md @axil /doc/user/admin_area/geo_nodes.md @axil
/doc/user/admin_area/labels.md @msedlakjakubowski /doc/user/admin_area/labels.md @msedlakjakubowski
/doc/user/admin_area/license.md @kpaizee /doc/user/admin_area/license.md @kpaizee
/doc/user/admin_area/license_file.md @sselhorn
/doc/user/admin_area/merge_requests_approvals.md @aqualls /doc/user/admin_area/merge_requests_approvals.md @aqualls
/doc/user/admin_area/moderate_users.md @eread /doc/user/admin_area/moderate_users.md @eread
/doc/user/admin_area/monitoring/background_migrations.md @aqualls /doc/user/admin_area/monitoring/background_migrations.md @aqualls
@ -657,8 +676,8 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/user/admin_area/settings/rate_limit_on_users_api.md @eread /doc/user/admin_area/settings/rate_limit_on_users_api.md @eread
/doc/user/admin_area/settings/third_party_offers.md @fneill /doc/user/admin_area/settings/third_party_offers.md @fneill
/doc/user/admin_area/settings/visibility_and_access_controls.md @aqualls /doc/user/admin_area/settings/visibility_and_access_controls.md @aqualls
/doc/user/analytics/ci_cd_analytics.md @rdickenson
/doc/user/analytics/ @fneill /doc/user/analytics/ @fneill
/doc/user/analytics/ci_cd_analytics.md @rdickenson
/doc/user/application_security/ @rdickenson /doc/user/application_security/ @rdickenson
/doc/user/application_security/cluster_image_scanning/index.md @ngaskill /doc/user/application_security/cluster_image_scanning/index.md @ngaskill
/doc/user/application_security/container_scanning/index.md @ngaskill /doc/user/application_security/container_scanning/index.md @ngaskill
@ -676,15 +695,18 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/user/compliance/license_compliance/index.md @rdickenson /doc/user/compliance/license_compliance/index.md @rdickenson
/doc/user/crm/index.md @msedlakjakubowski /doc/user/crm/index.md @msedlakjakubowski
/doc/user/discussions/index.md @aqualls /doc/user/discussions/index.md @aqualls
/doc/user/feature_flags.md @marcia
/doc/user/group/index.md @eread
/doc/user/group/clusters/index.md @sselhorn /doc/user/group/clusters/index.md @sselhorn
/doc/user/group/contribution_analytics/index.md @fneill /doc/user/group/contribution_analytics/index.md @fneill
/doc/user/group/custom_project_templates.md @ngaskill /doc/user/group/custom_project_templates.md @ngaskill
/doc/user/group/devops_adoption/index.md @fneill /doc/user/group/devops_adoption/index.md @fneill
/doc/user/group/epics/epic_boards.md @msedlakjakubowski /doc/user/group/epics/epic_boards.md @msedlakjakubowski
/doc/user/group/epics/index.md @msedlakjakubowski /doc/user/group/epics/index.md @msedlakjakubowski
/doc/user/group/epics/linked_epics.md @msedlakjakubowski
/doc/user/group/epics/manage_epics.md @msedlakjakubowski /doc/user/group/epics/manage_epics.md @msedlakjakubowski
/doc/user/group/import/index.md @ngaskill
/doc/user/group/index.md @eread /doc/user/group/index.md @eread
/doc/user/group/import/index.md @ngaskill
/doc/user/group/insights/index.md @fneill /doc/user/group/insights/index.md @fneill
/doc/user/group/issues_analytics/index.md @msedlakjakubowski /doc/user/group/issues_analytics/index.md @msedlakjakubowski
/doc/user/group/iterations/index.md @msedlakjakubowski /doc/user/group/iterations/index.md @msedlakjakubowski
@ -694,6 +716,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/user/group/saml_sso/group_managed_accounts.md @eread /doc/user/group/saml_sso/group_managed_accounts.md @eread
/doc/user/group/saml_sso/index.md @eread /doc/user/group/saml_sso/index.md @eread
/doc/user/group/saml_sso/scim_setup.md @eread /doc/user/group/saml_sso/scim_setup.md @eread
/doc/user/group/settings/group_access_tokens.md @eread
/doc/user/group/settings/import_export.md @ngaskill /doc/user/group/settings/import_export.md @ngaskill
/doc/user/group/subgroups/index.md @eread /doc/user/group/subgroups/index.md @eread
/doc/user/group/value_stream_analytics/index.md @fneill /doc/user/group/value_stream_analytics/index.md @fneill
@ -704,11 +727,13 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/user/infrastructure/clusters/manage/management_project_applications/falco.md @ngaskill /doc/user/infrastructure/clusters/manage/management_project_applications/falco.md @ngaskill
/doc/user/infrastructure/clusters/manage/management_project_applications/fluentd.md @ngaskill /doc/user/infrastructure/clusters/manage/management_project_applications/fluentd.md @ngaskill
/doc/user/infrastructure/iac/ @sselhorn /doc/user/infrastructure/iac/ @sselhorn
/doc/user/infrastructure/index.md @ssehorn /doc/user/infrastructure/index.md @sselhorn
/doc/user/markdown.md @aqualls /doc/user/markdown.md @aqualls
/doc/user/packages/ @ngaskill /doc/user/packages/ @ngaskill
/doc/user/packages/infrastructure_registry/index.md @sselhorn /doc/user/packages/infrastructure_registry/index.md @sselhorn
/doc/user/packages/terraform_module_registry/index.md @sselhorn /doc/user/packages/terraform_module_registry/index.md @sselhorn
/doc/user/packages/workflows/project_registry.md @ngaskill
/doc/user/packages/workflows/working_with_monorepos.md @ngaskill
/doc/user/permissions.md @eread /doc/user/permissions.md @eread
/doc/user/profile/ @eread /doc/user/profile/ @eread
/doc/user/profile/notifications.md @msedlakjakubowski /doc/user/profile/notifications.md @msedlakjakubowski
@ -734,6 +759,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/user/project/integrations/prometheus.md @ngaskill /doc/user/project/integrations/prometheus.md @ngaskill
/doc/user/project/issue_board.md @msedlakjakubowski /doc/user/project/issue_board.md @msedlakjakubowski
/doc/user/project/issues/ @msedlakjakubowski /doc/user/project/issues/ @msedlakjakubowski
/doc/user/project/issues/csv_import.md @ngaskill
/doc/user/project/labels.md @msedlakjakubowski /doc/user/project/labels.md @msedlakjakubowski
/doc/user/project/members/index.md @eread /doc/user/project/members/index.md @eread
/doc/user/project/members/share_project_with_groups.md @fneill /doc/user/project/members/share_project_with_groups.md @fneill
@ -748,7 +774,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/user/project/merge_requests/test_coverage_visualization.md @eread /doc/user/project/merge_requests/test_coverage_visualization.md @eread
/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md @eread /doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md @eread
/doc/user/project/milestones/ @msedlakjakubowski /doc/user/project/milestones/ @msedlakjakubowski
/doc/user/project/pages/ @rdickenson /doc/user/project/pages/ @aqualls
/doc/user/project/protected_branches.md @aqualls /doc/user/project/protected_branches.md @aqualls
/doc/user/project/protected_tags.md @aqualls /doc/user/project/protected_tags.md @aqualls
/doc/user/project/push_options.md @aqualls /doc/user/project/push_options.md @aqualls
@ -768,6 +794,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/user/project/wiki/group.md @aqualls /doc/user/project/wiki/group.md @aqualls
/doc/user/project/wiki/index.md @aqualls /doc/user/project/wiki/index.md @aqualls
/doc/user/project/working_with_projects.md @fneill /doc/user/project/working_with_projects.md @fneill
/doc/user/public_access.md @fneill
/doc/user/reserved_names.md @fneill /doc/user/reserved_names.md @fneill
/doc/user/search/advanced_search.md @rdickenson /doc/user/search/advanced_search.md @rdickenson
/doc/user/search/index.md @aqualls /doc/user/search/index.md @aqualls

View file

@ -93,9 +93,9 @@ export default {
</a> </a>
</div> </div>
<div <div
v-safe-html="content"
class="gl-white-space-pre-wrap! gl-text-transparent" class="gl-white-space-pre-wrap! gl-text-transparent"
data-testid="content" data-testid="content"
v-text="content"
></div> ></div>
</div> </div>
</gl-intersection-observer> </gl-intersection-observer>

View file

@ -26,6 +26,7 @@ class Projects::MilestonesController < Projects::ApplicationController
respond_to do |format| respond_to do |format|
format.html do format.html do
@milestone_states = Milestone.states_count(@project)
# We need to show group milestones in the JSON response # We need to show group milestones in the JSON response
# so that people can filter by and assign group milestones, # so that people can filter by and assign group milestones,
# but we don't need to show them on the project milestones page itself. # but we don't need to show them on the project milestones page itself.

View file

@ -63,21 +63,6 @@ module TimeboxesHelper
issues.size issues.size
end end
# Returns count of milestones for different states
# Uses explicit hash keys as the 'opened' state URL params differs from the db value
# and we need to add the total
# rubocop: disable CodeReuse/ActiveRecord
def milestone_counts(milestones)
counts = milestones.reorder(nil).group(:state).count
{
opened: counts['active'] || 0,
closed: counts['closed'] || 0,
all: counts.values.sum || 0
}
end
# rubocop: enable CodeReuse/ActiveRecord
def milestone_progress_tooltip_text(milestone) def milestone_progress_tooltip_text(milestone)
has_issues = milestone.total_issues_count > 0 has_issues = milestone.total_issues_count > 0

View file

@ -12,16 +12,29 @@
path: '-/milestones/new', label: 'New milestone', path: '-/milestones/new', label: 'New milestone',
include_groups: true, type: :milestones include_groups: true, type: :milestones
.top-area - if @milestone_states.any? { |name, count| count > 0 }
= render 'shared/milestones_filter', counts: @milestone_states .top-area
.nav-controls = render 'shared/milestones_filter', counts: @milestone_states
= render 'shared/milestones/search_form' .nav-controls
= render 'shared/milestones/search_form'
- if @milestones.blank? - if @milestones.blank?
= render 'shared/empty_states/milestones' = render 'shared/empty_states/milestones_tab', active_tab: params[:state] do
- if current_user
.page-title-controls
= render 'shared/new_project_item_select',
path: '-/milestones/new', label: 'New milestone',
include_groups: true, type: :milestones
- else
.milestones
%ul.content-list
- @milestones.each do |milestone|
= render 'milestone', milestone: milestone
= paginate @milestones, theme: 'gitlab'
- else - else
.milestones = render 'shared/empty_states/milestones' do
%ul.content-list - if current_user
- @milestones.each do |milestone| .page-title-controls
= render 'milestone', milestone: milestone = render 'shared/new_project_item_select',
= paginate @milestones, theme: 'gitlab' path: '-/milestones/new', label: 'New milestone',
include_groups: true, type: :milestones

View file

@ -1,23 +1,32 @@
- page_title _("Milestones") - page_title _("Milestones")
- add_page_specific_style 'page_bundles/milestone' - add_page_specific_style 'page_bundles/milestone'
.top-area - if @milestone_states.any? { |name, count| count > 0 }
= render 'shared/milestones_filter', counts: @milestone_states .top-area
= render 'shared/milestones_filter', counts: @milestone_states
.nav-controls .nav-controls
= render 'shared/milestones/search_form' = render 'shared/milestones/search_form'
= render 'shared/milestones_sort_dropdown' = render 'shared/milestones_sort_dropdown'
- if can?(current_user, :admin_milestone, @group) - if can?(current_user, :admin_milestone, @group)
= link_to _('New milestone'), new_group_milestone_path(@group), class: "btn gl-button btn-confirm", data: { qa_selector: "new_group_milestone_link" } = link_to _('New milestone'), new_group_milestone_path(@group), class: "btn gl-button btn-confirm", data: { qa_selector: "new_group_milestone_link" }
- if @milestones.blank? - if @milestones.blank?
= render 'shared/empty_states/milestones' = render 'shared/empty_states/milestones_tab', learn_more_path: help_page_path('user/group/milestones') do
- if can?(current_user, :admin_milestone, @group)
.text-center
= link_to _('New milestone'), new_group_milestone_path(@group), class: "btn gl-button btn-confirm", data: { qa_selector: "new_group_milestone_link" }
- else
.milestones
%ul.content-list
- @milestones.each do |milestone|
- if milestone.project_milestone?
= render 'projects/milestones/milestone', milestone: milestone
- else
= render 'milestone', milestone: milestone
= paginate @milestones, theme: "gitlab"
- else - else
.milestones = render 'shared/empty_states/milestones', learn_more_path: help_page_path('user/group/milestones') do
%ul.content-list - if can?(current_user, :admin_milestone, @group)
- @milestones.each do |milestone| .text-center
- if milestone.project_milestone? = link_to _('New milestone'), new_group_milestone_path(@group), class: "btn gl-button btn-confirm", data: { qa_selector: "new_group_milestone_link" }
= render 'projects/milestones/milestone', milestone: milestone
- else
= render 'milestone', milestone: milestone
= paginate @milestones, theme: "gitlab"

View file

@ -1,24 +1,36 @@
- page_title _('Milestones') - page_title _('Milestones')
- add_page_specific_style 'page_bundles/milestone' - add_page_specific_style 'page_bundles/milestone'
.top-area - if @milestone_states.any? { |name, count| count > 0 }
= render 'shared/milestones_filter', counts: milestone_counts(@project.milestones) .top-area
= render 'shared/milestones_filter', counts: @milestone_states
.nav-controls .nav-controls
= render 'shared/milestones/search_form' = render 'shared/milestones/search_form'
= render 'shared/milestones_sort_dropdown' = render 'shared/milestones_sort_dropdown'
- if can?(current_user, :admin_milestone, @project) - if can?(current_user, :admin_milestone, @project)
= link_to new_project_milestone_path(@project), class: 'gl-button btn btn-confirm', data: { qa_selector: "new_project_milestone_link" }, title: _('New milestone') do = link_to new_project_milestone_path(@project), class: 'gl-button btn btn-confirm', data: { qa_selector: "new_project_milestone_link" }, title: _('New milestone') do
= _('New milestone') = _('New milestone')
- if @milestones.blank? - if @milestones.blank?
= render 'shared/empty_states/milestones' = render 'shared/empty_states/milestones_tab' do
- if can?(current_user, :admin_milestone, @project)
.text-center
= link_to new_project_milestone_path(@project), class: 'gl-button btn btn-confirm', data: { qa_selector: "new_project_milestone_link" }, title: _('New milestone') do
= _('New milestone')
- else
.milestones
#js-delete-milestone-modal
#promote-milestone-modal
%ul.content-list
= render @milestones
= paginate @milestones, theme: 'gitlab'
- else - else
.milestones = render 'shared/empty_states/milestones' do
#js-delete-milestone-modal - if can?(current_user, :admin_milestone, @project)
#promote-milestone-modal .text-center
= link_to new_project_milestone_path(@project), class: 'gl-button btn btn-confirm', data: { qa_selector: "new_project_milestone_link" }, title: _('New milestone') do
%ul.content-list = _('New milestone')
= render @milestones
= paginate @milestones, theme: 'gitlab'

View file

@ -1,7 +1,13 @@
- learn_more_path = local_assigns.fetch(:learn_more_path, help_page_path('user/project/milestones/index'))
- learn_more_link = link_to _('Learn more.'), learn_more_path
.row.empty-state .row.empty-state
.col-12 .col-12
.svg-content .svg-content
= image_tag 'illustrations/milestone_burndown_chart.svg' = image_tag 'illustrations/milestone_burndown_chart.svg'
.col-12 .col-12
.text-content .text-content
%h4.text-center= _('No milestones to show') %h4= s_('Milestones|Use milestones to track issues and merge requests over a fixed period of time')
%p.state-description
= s_('Milestones|Organize issues and merge requests into a cohesive group, and set an optional start and due dates. %{learn_more_link}').html_safe % { learn_more_link: learn_more_link }
= yield

View file

@ -0,0 +1,17 @@
- learn_more_path = local_assigns.fetch(:learn_more_path, help_page_path('user/project/milestones/index'))
- learn_more_link = link_to _('Learn more.'), learn_more_path
- closed_tab_selected = params[:state] == 'closed'
.row.empty-state
.col-12
.svg-content
= image_tag 'illustrations/milestone_burndown_chart.svg'
.col-12
.text-content
- if closed_tab_selected
%h4.text-center= s_('Milestones|There are no closed milestones')
- else
%h4.text-center= s_('Milestones|There are no open milestones')
%p.state-description
= s_('Milestones|Create a milestone to better track your issues and merge requests. %{learn_more_link}').html_safe % { learn_more_link: learn_more_link }
= yield

View file

@ -61,8 +61,7 @@ To create an Auditor user:
1. On the left sidebar, select **Overview > Users**. 1. On the left sidebar, select **Overview > Users**.
1. Create a new user or edit an existing one, and in the **Access** section 1. Create a new user or edit an existing one, and in the **Access** section
select Auditor. select Auditor.
1. Select **Create user** or **Save changes** if you created a new user or 1. If you created a user, select **Create user**. For an existing user, select **Save changes**.
edited an existing one respectively.
To revoke Auditor permissions from a user, make them a Regular user by To revoke Auditor permissions from a user, make them a Regular user by
following the previous steps. following the previous steps.

View file

@ -619,7 +619,7 @@ Note the following:
environment variable so that the Gitaly certificate is trusted. For example: environment variable so that the Gitaly certificate is trusted. For example:
```shell ```shell
sudo SSL_CERT_DIR=/etc/gitlab/trusted_certs /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dial-nodes sudo SSL_CERT_DIR=/etc/gitlab/trusted-certs /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dial-nodes
``` ```
- You can configure Praefect servers with both an unencrypted listening address - You can configure Praefect servers with both an unencrypted listening address

View file

@ -1,6 +1,6 @@
--- ---
stage: Release stage: Create
group: Release group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
description: 'Learn how to administer GitLab Pages.' description: 'Learn how to administer GitLab Pages.'
--- ---
@ -1393,15 +1393,15 @@ in all of your GitLab Pages instances.
Connections will time out when using a Network Load Balancer with client IP preservation enabled and [the request is looped back to the source server](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-troubleshooting.html#loopback-timeout). Connections will time out when using a Network Load Balancer with client IP preservation enabled and [the request is looped back to the source server](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-troubleshooting.html#loopback-timeout).
This can happen to GitLab instances with multiple servers This can happen to GitLab instances with multiple servers
running both the core GitLab application and GitLab Pages. This can also happen when a single running both the core GitLab application and GitLab Pages. This can also happen when a single
container is running both the core GitLab application and GitLab Pages. container is running both the core GitLab application and GitLab Pages.
AWS [recommends using an IP target type](https://aws.amazon.com/premiumsupport/knowledge-center/target-connection-fails-load-balancer/) AWS [recommends using an IP target type](https://aws.amazon.com/premiumsupport/knowledge-center/target-connection-fails-load-balancer/)
to resolve this issue. to resolve this issue.
Turning off [client IP preservation](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-target-groups.html#client-ip-preservation) Turning off [client IP preservation](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-target-groups.html#client-ip-preservation)
may resolve this issue when the core GitLab application and GitLab Pages run on the same host or may resolve this issue when the core GitLab application and GitLab Pages run on the same host or
container. container.
### 500 error with `securecookie: failed to generate random iv` and `Failed to save the session` ### 500 error with `securecookie: failed to generate random iv` and `Failed to save the session`

View file

@ -1,6 +1,6 @@
--- ---
stage: Release stage: Create
group: Release group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
--- ---

View file

@ -21,7 +21,7 @@ The readiness probe checks whether the Sidekiq workers are ready to process jobs
GET /readiness GET /readiness
``` ```
Assuming you set up Sidekiq's address and port to be `localhost` and `8092` respectively, If you set Sidekiq's address as `localhost` and port as `8092`,
here's an example request: here's an example request:
```shell ```shell
@ -44,7 +44,7 @@ Checks whether the Sidekiq cluster is running.
GET /liveness GET /liveness
``` ```
Assuming you set up Sidekiq's address and port to be `localhost` and `8092` respectively, If you set Sidekiq's address as `localhost` and port as `8092`,
here's an example request: here's an example request:
```shell ```shell

View file

@ -20,7 +20,7 @@ GET groups/:id/access_tokens
| Attribute | Type | required | Description | | Attribute | Type | required | Description |
|-----------|---------|----------|---------------------| |-----------|---------|----------|---------------------|
| `id` | integer or string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) | | `id` | integer or string | yes | ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
```shell ```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/<group_id>/access_tokens" curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/<group_id>/access_tokens"
@ -44,6 +44,41 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
] ]
``` ```
## Get a group access token
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82714) in GitLab 14.10.
Get a [group access token](../user/group/settings/group_access_tokens.md) by ID.
```plaintext
GET groups/:id/access_tokens/:token_id
```
| Attribute | Type | required | Description |
|-----------|---------|----------|---------------------|
| `id` | integer or string | yes | ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
| `token_id` | integer or string | yes | ID of the group access token |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/<group_id>/access_tokens/<token_id>"
```
```json
{
"user_id" : 141,
"scopes" : [
"api"
],
"name" : "token",
"expires_at" : "2021-01-31",
"id" : 42,
"active" : true,
"created_at" : "2021-01-20T22:11:48.151Z",
"revoked" : false,
"access_level": 40
}
```
## Create a group access token ## Create a group access token
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77236) in GitLab 14.7. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77236) in GitLab 14.7.
@ -56,11 +91,11 @@ POST groups/:id/access_tokens
| Attribute | Type | required | Description | | Attribute | Type | required | Description |
|-----------|---------|----------|---------------------| |-----------|---------|----------|---------------------|
| `id` | integer or string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) | | `id` | integer or string | yes | ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
| `name` | String | yes | The name of the group access token | | `name` | String | yes | Name of the group access token |
| `scopes` | `Array[String]` | yes | [List of scopes](../user/group/settings/group_access_tokens.md#scopes-for-a-group-access-token) | | `scopes` | `Array[String]` | yes | [List of scopes](../user/group/settings/group_access_tokens.md#scopes-for-a-group-access-token) |
| `access_level` | Integer | no | A valid access level. Default value is 40 (Maintainer). Other allowed values are 10 (Guest), 20 (Reporter), and 30 (Developer). | | `access_level` | Integer | no | A valid access level. Default value is 40 (Maintainer). Other allowed values are 10 (Guest), 20 (Reporter), and 30 (Developer). |
| `expires_at` | Date | no | The token expires at midnight UTC on that date | | `expires_at` | Date | no | Token expires at midnight UTC on that date |
```shell ```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
@ -99,8 +134,8 @@ DELETE groups/:id/access_tokens/:token_id
| Attribute | Type | required | Description | | Attribute | Type | required | Description |
|-----------|---------|----------|---------------------| |-----------|---------|----------|---------------------|
| `id` | integer or string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) | | `id` | integer or string | yes | ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
| `token_id` | integer or string | yes | The ID of the group access token | | `token_id` | integer or string | yes | ID of the group access token |
```shell ```shell
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/<group_id>/access_tokens/<token_id>" curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/<group_id>/access_tokens/<token_id>"

View file

@ -1,6 +1,6 @@
--- ---
stage: Release stage: Create
group: Release group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
--- ---

View file

@ -1,6 +1,6 @@
--- ---
stage: Release stage: Create
group: Release group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
--- ---

View file

@ -20,7 +20,7 @@ GET projects/:id/access_tokens
| Attribute | Type | required | Description | | Attribute | Type | required | Description |
|-----------|---------|----------|---------------------| |-----------|---------|----------|---------------------|
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) | | `id` | integer or string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
```shell ```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens" curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens"
@ -44,6 +44,42 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
] ]
``` ```
## Get a project access token
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82714) in GitLab 14.10.
Get a [project access token](../user/project/settings/project_access_tokens.md) by ID.
```plaintext
GET projects/:id/access_tokens/:token_id
```
| Attribute | Type | required | Description |
|-----------|---------|----------|---------------------|
| `id` | integer or string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
| `token_id` | integer or string | yes | ID of the project access token |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens/<token_id>"
```
```json
{
"user_id" : 141,
"scopes" : [
"api"
],
"name" : "token",
"expires_at" : "2021-01-31",
"id" : 42,
"active" : true,
"created_at" : "2021-01-20T22:11:48.151Z",
"revoked" : false,
"access_level": 40,
"last_used_at": "2022-03-15T11:05:42.437Z"
}
```
## Create a project access token ## Create a project access token
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55408) in GitLab 13.10. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55408) in GitLab 13.10.
@ -56,11 +92,11 @@ POST projects/:id/access_tokens
| Attribute | Type | required | Description | | Attribute | Type | required | Description |
|-----------|---------|----------|---------------------| |-----------|---------|----------|---------------------|
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) | | `id` | integer or string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
| `name` | String | yes | The name of the project access token | | `name` | String | yes | Name of the project access token |
| `scopes` | `Array[String]` | yes | [List of scopes](../user/project/settings/project_access_tokens.md#scopes-for-a-project-access-token) | | `scopes` | `Array[String]` | yes | [List of scopes](../user/project/settings/project_access_tokens.md#scopes-for-a-project-access-token) |
| `access_level` | Integer | no | A valid access level. Default value is 40 (Maintainer). Other allowed values are 10 (Guest), 20 (Reporter), and 30 (Developer). | | `access_level` | Integer | no | A valid access level. Default value is 40 (Maintainer). Other allowed values are 10 (Guest), 20 (Reporter), and 30 (Developer). |
| `expires_at` | Date | no | The token expires at midnight UTC on that date | | `expires_at` | Date | no | Token expires at midnight UTC on that date |
```shell ```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
@ -99,8 +135,8 @@ DELETE projects/:id/access_tokens/:token_id
| Attribute | Type | required | Description | | Attribute | Type | required | Description |
|-----------|---------|----------|---------------------| |-----------|---------|----------|---------------------|
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) | | `id` | integer or string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
| `token_id` | integer or string | yes | The ID of the project access token | | `token_id` | integer or string | yes | ID of the project access token |
```shell ```shell
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens/<token_id>" curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens/<token_id>"

View file

@ -15,7 +15,7 @@ This feature is in a [Beta](../../policy/alpha-beta-support.md#beta-features) st
It may be useful to require additional approvals before deploying to certain protected environments (for example, production). This pre-deployment approval requirement is useful to accommodate testing, security, or compliance processes that must happen before each deployment. It may be useful to require additional approvals before deploying to certain protected environments (for example, production). This pre-deployment approval requirement is useful to accommodate testing, security, or compliance processes that must happen before each deployment.
When a protected environment requires one or more approvals, all deployments to that environment become blocked and wait for the required approvals before running. When a protected environment requires one or more approvals, all deployments to that environment become blocked and wait for the required approvals from the `Allowed to Deploy` list before running.
NOTE: NOTE:
See the [epic](https://gitlab.com/groups/gitlab-org/-/epics/6832) for planned features. See the [epic](https://gitlab.com/groups/gitlab-org/-/epics/6832) for planned features.

View file

@ -729,6 +729,19 @@ Do not use **Reporter permissions**. A user who is assigned the Reporter role ha
Use title case for **Repository Mirroring**. Use title case for **Repository Mirroring**.
## respectively
Avoid **respectively** and be more precise instead.
Use:
- To create a user, select **Create user**. For an existing user, select **Save changes**.
Instead of:
- Select **Create user** or **Save changes** if you created a new user or
edited an existing one respectively.
## roles ## roles
Do not use **roles** and [**permissions**](#permissions) interchangeably. Each user is assigned a role. Each role includes a set of permissions. Do not use **roles** and [**permissions**](#permissions) interchangeably. Each user is assigned a role. Each role includes a set of permissions.

View file

@ -730,6 +730,11 @@ Refer to the documentation for your SAML Identity Provider for information on ho
The [Generated passwords for users created through integrated authentication](../security/passwords_for_integrated_authentication_methods.md) guide provides an overview of how GitLab generates and sets passwords for users created via SAML. The [Generated passwords for users created through integrated authentication](../security/passwords_for_integrated_authentication_methods.md) guide provides an overview of how GitLab generates and sets passwords for users created via SAML.
## Link SAML identity for an existing user
A user can manually link their SAML identity to an existing GitLab account by following the steps in
[Enable OmniAuth for an existing user](omniauth.md#enable-omniauth-for-an-existing-user).
## Configuring Group SAML on a self-managed GitLab instance **(PREMIUM SELF)** ## Configuring Group SAML on a self-managed GitLab instance **(PREMIUM SELF)**
For information on the GitLab.com implementation, please see the [SAML SSO for GitLab.com groups page](../user/group/saml_sso). For information on the GitLab.com implementation, please see the [SAML SSO for GitLab.com groups page](../user/group/saml_sso).

View file

@ -1,7 +1,7 @@
--- ---
type: concepts type: concepts
stage: Release stage: Create
group: Release group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
--- ---

View file

@ -1,7 +1,7 @@
--- ---
disqus_identifier: 'https://docs.gitlab.com/ee/user/project/pages/getting_started_part_three.html' disqus_identifier: 'https://docs.gitlab.com/ee/user/project/pages/getting_started_part_three.html'
stage: Release stage: Create
group: Release group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
--- ---

View file

@ -1,8 +1,8 @@
--- ---
type: reference type: reference
description: "Automatic Let's Encrypt SSL certificates for GitLab Pages." description: "Automatic Let's Encrypt SSL certificates for GitLab Pages."
stage: Release stage: Create
group: Release group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
--- ---

View file

@ -1,7 +1,7 @@
--- ---
type: concepts type: concepts
stage: Release stage: Create
group: Release group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
--- ---

View file

@ -1,7 +1,7 @@
--- ---
type: reference, howto type: reference, howto
stage: Release stage: Create
group: Release group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
--- ---

View file

@ -1,7 +1,7 @@
--- ---
type: reference, howto type: reference, howto
stage: Release stage: Create
group: Release group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
--- ---

View file

@ -1,6 +1,6 @@
--- ---
stage: Release stage: Create
group: Release group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
--- ---

View file

@ -1,6 +1,6 @@
--- ---
stage: Release stage: Create
group: Release group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
--- ---

View file

@ -1,6 +1,6 @@
--- ---
stage: Release stage: Create
group: Release group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
--- ---

View file

@ -1,7 +1,7 @@
--- ---
description: 'Learn how to use GitLab Pages to deploy a static website at no additional cost.' description: 'Learn how to use GitLab Pages to deploy a static website at no additional cost.'
stage: Release stage: Create
group: Release group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
--- ---

View file

@ -1,6 +1,6 @@
--- ---
stage: Release stage: Create
group: Release group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
--- ---

View file

@ -1,6 +1,6 @@
--- ---
stage: Release stage: Create
group: Release group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
--- ---

View file

@ -1,6 +1,6 @@
--- ---
stage: Release stage: Create
group: Release group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
--- ---

View file

@ -27,6 +27,28 @@ module API
present paginate(tokens), with: Entities::ResourceAccessToken, resource: resource present paginate(tokens), with: Entities::ResourceAccessToken, resource: resource
end end
desc 'Get an access token for the specified resource by ID' do
detail 'This feature was introduced in GitLab 14.10.'
end
params do
requires :id, type: String, desc: "The #{source_type} ID"
requires :token_id, type: String, desc: "The ID of the token"
end
get ":id/access_tokens/:token_id" do
resource = find_source(source_type, params[:id])
next unauthorized! unless current_user.can?(:read_resource_access_tokens, resource)
token = find_token(resource, params[:token_id])
if token.nil?
next not_found!("Could not find #{source_type} access token with token_id: #{params[:token_id]}")
end
resource.members.load
present token, with: Entities::ResourceAccessToken, resource: resource
end
desc 'Revoke a resource access token' do desc 'Revoke a resource access token' do
detail 'This feature was introduced in GitLab 13.9.' detail 'This feature was introduced in GitLab 13.9.'
end end

View file

@ -17,6 +17,10 @@ module Gitlab
Runner.new(direction: :down, migrations: migrations_for_down, result_dir: BASE_RESULT_DIR.join('down')) Runner.new(direction: :down, migrations: migrations_for_down, result_dir: BASE_RESULT_DIR.join('down'))
end end
def background_migrations
TestBackgroundRunner.new(result_dir: BASE_RESULT_DIR.join('background_migrations'))
end
def migration_context def migration_context
@migration_context ||= ApplicationRecord.connection.migration_context @migration_context ||= ApplicationRecord.connection.migration_context
end end

View file

@ -4,12 +4,10 @@ module Gitlab
module Database module Database
module Migrations module Migrations
class TestBackgroundRunner class TestBackgroundRunner
# TODO - build a rake task to call this method, and support it in the gitlab-com-database-testing project. attr_reader :result_dir
# Until then, we will inject a migration with a very high timestamp during database testing
# that calls this class to run jobs
# See https://gitlab.com/gitlab-org/database-team/gitlab-com-database-testing/-/issues/41 for details
def initialize def initialize(result_dir:)
@result_dir = result_dir
@job_coordinator = Gitlab::BackgroundMigration.coordinator_for_database(Gitlab::Database::MAIN_DATABASE_NAME) @job_coordinator = Gitlab::BackgroundMigration.coordinator_for_database(Gitlab::Database::MAIN_DATABASE_NAME)
end end
@ -24,18 +22,30 @@ module Gitlab
# without .to_f, we do integer division # without .to_f, we do integer division
# For example, 3.minutes / 2 == 1.minute whereas 3.minutes / 2.to_f == (1.minute + 30.seconds) # For example, 3.minutes / 2 == 1.minute whereas 3.minutes / 2.to_f == (1.minute + 30.seconds)
duration_per_migration_type = for_duration / jobs_to_run.count.to_f duration_per_migration_type = for_duration / jobs_to_run.count.to_f
jobs_to_run.each do |_migration_name, jobs| jobs_to_run.each do |migration_name, jobs|
run_until = duration_per_migration_type.from_now run_until = duration_per_migration_type.from_now
jobs.shuffle.each do |j|
break if run_until <= Time.current
run_job(j) run_jobs_for_migration(migration_name: migration_name, jobs: jobs, run_until: run_until)
end
end end
end end
private private
def run_jobs_for_migration(migration_name:, jobs:, run_until:)
per_background_migration_result_dir = File.join(@result_dir, migration_name)
instrumentation = Instrumentation.new(result_dir: per_background_migration_result_dir)
batch_names = (1..).each.lazy.map { |i| "batch_#{i}"}
jobs.shuffle.each do |j|
break if run_until <= Time.current
instrumentation.observe(version: nil, name: batch_names.next, connection: ActiveRecord::Migration.connection) do
run_job(j)
end
end
end
def run_job(job) def run_job(job)
Gitlab::BackgroundMigration.perform(job.args[0], job.args[1]) Gitlab::BackgroundMigration.perform(job.args[0], job.args[1])
end end

View file

@ -307,6 +307,13 @@ namespace :gitlab do
task down: :environment do task down: :environment do
Gitlab::Database::Migrations::Runner.down.run Gitlab::Database::Migrations::Runner.down.run
end end
desc 'Sample traditional background migrations with instrumentation'
task :sample_background_migrations, [:duration_s] => [:environment] do |_t, args|
duration = args[:duration_s]&.to_i&.seconds || 30.minutes # Default of 30 minutes
Gitlab::Database::Migrations::Runner.background_migrations.run_jobs(for_duration: duration)
end
end end
desc 'Run all pending batched migrations' desc 'Run all pending batched migrations'

View file

@ -24091,6 +24091,9 @@ msgstr ""
msgid "Milestones|Completed Issues (closed)" msgid "Milestones|Completed Issues (closed)"
msgstr "" msgstr ""
msgid "Milestones|Create a milestone to better track your issues and merge requests. %{learn_more_link}"
msgstr ""
msgid "Milestones|Delete milestone" msgid "Milestones|Delete milestone"
msgstr "" msgstr ""
@ -24109,6 +24112,9 @@ msgstr ""
msgid "Milestones|Ongoing Issues (open and assigned)" msgid "Milestones|Ongoing Issues (open and assigned)"
msgstr "" msgstr ""
msgid "Milestones|Organize issues and merge requests into a cohesive group, and set an optional start and due dates. %{learn_more_link}"
msgstr ""
msgid "Milestones|Project Milestone" msgid "Milestones|Project Milestone"
msgstr "" msgstr ""
@ -24127,12 +24133,21 @@ msgstr ""
msgid "Milestones|Reopen Milestone" msgid "Milestones|Reopen Milestone"
msgstr "" msgstr ""
msgid "Milestones|There are no closed milestones"
msgstr ""
msgid "Milestones|There are no open milestones"
msgstr ""
msgid "Milestones|This action cannot be reversed." msgid "Milestones|This action cannot be reversed."
msgstr "" msgstr ""
msgid "Milestones|Unstarted Issues (open and unassigned)" msgid "Milestones|Unstarted Issues (open and unassigned)"
msgstr "" msgstr ""
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively." msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr "" msgstr ""
@ -25208,9 +25223,6 @@ msgstr ""
msgid "No milestone" msgid "No milestone"
msgstr "" msgstr ""
msgid "No milestones to show"
msgstr ""
msgid "No namespace" msgid "No namespace"
msgstr "" msgstr ""

View file

@ -66,7 +66,7 @@ RSpec.describe 'Group milestones' do
context 'when no milestones' do context 'when no milestones' do
it 'renders no milestones text' do it 'renders no milestones text' do
visit group_milestones_path(group) visit group_milestones_path(group)
expect(page).to have_content('No milestones to show') expect(page).to have_content('Use milestones to track issues and merge requests')
end end
end end

View file

@ -21,7 +21,7 @@ RSpec.describe "User deletes milestone", :js do
click_button("Delete") click_button("Delete")
click_button("Delete milestone") click_button("Delete milestone")
expect(page).to have_content("No milestones to show") expect(page).to have_content("Use milestones to track issues and merge requests over a fixed period of time")
visit(activity_project_path(project)) visit(activity_project_path(project))

View file

@ -0,0 +1,31 @@
{
"type": "object",
"required": [
"id",
"name",
"user_id",
"active",
"created_at",
"expires_at",
"revoked",
"access_level",
"scopes",
"last_used_at"
],
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"user_id": { "type": "integer" },
"active": { "type": "boolean" },
"created_at": { "type": "string", "format": "date-time" },
"expires_at": { "type": ["string", "null"], "format": "date" },
"revoked": { "type": "boolean" },
"access_level": { "type": "integer" },
"scopes": {
"type": "array",
"items": { "type": "string" }
},
"last_used_at": { "type": ["string", "null"], "format": "date-time" }
},
"additionalProperties": false
}

View file

@ -0,0 +1,4 @@
{
"type": "array",
"items": { "$ref": "resource_access_token.json" }
}

View file

@ -24,34 +24,6 @@ RSpec.describe TimeboxesHelper do
end end
end end
describe '#milestone_counts' do
let(:project) { create(:project) }
let(:counts) { helper.milestone_counts(project.milestones) }
context 'when there are milestones' do
it 'returns the correct counts' do
create_list(:active_milestone, 2, project: project)
create(:closed_milestone, project: project)
expect(counts).to eq(opened: 2, closed: 1, all: 3)
end
end
context 'when there are only milestones of one type' do
it 'returns the correct counts' do
create_list(:active_milestone, 2, project: project)
expect(counts).to eq(opened: 2, closed: 0, all: 2)
end
end
context 'when there are no milestones' do
it 'returns the correct counts' do
expect(counts).to eq(opened: 0, closed: 0, all: 0)
end
end
end
describe "#group_milestone_route" do describe "#group_milestone_route" do
let(:group) { build_stubbed(:group) } let(:group) { build_stubbed(:group) }
let(:subgroup) { build_stubbed(:group, parent: group, name: "Test Subgrp") } let(:subgroup) { build_stubbed(:group, parent: group, name: "Test Subgrp") }

View file

@ -124,4 +124,16 @@ RSpec.describe Gitlab::Database::Migrations::Runner do
expect(metadata).to match('version' => described_class::SCHEMA_VERSION) expect(metadata).to match('version' => described_class::SCHEMA_VERSION)
end end
end end
describe '.background_migrations' do
it 'is a TestBackgroundRunner' do
expect(described_class.background_migrations).to be_a(Gitlab::Database::Migrations::TestBackgroundRunner)
end
it 'is configured with a result dir of /background_migrations' do
runner = described_class.background_migrations
expect(runner.result_dir).to eq(described_class::BASE_RESULT_DIR.join( 'background_migrations'))
end
end
end end

View file

@ -11,11 +11,17 @@ RSpec.describe Gitlab::Database::Migrations::TestBackgroundRunner, :redis do
Sidekiq::Testing.disable! { ex.run } Sidekiq::Testing.disable! { ex.run }
end end
let(:result_dir) { Dir.mktmpdir }
after do
FileUtils.rm_rf(result_dir)
end
context 'without jobs to run' do context 'without jobs to run' do
it 'returns immediately' do it 'returns immediately' do
runner = described_class.new runner = described_class.new(result_dir: result_dir)
expect(runner).not_to receive(:run_job) expect(runner).not_to receive(:run_job)
described_class.new.run_jobs(for_duration: 1.second) described_class.new(result_dir: result_dir).run_jobs(for_duration: 1.second)
end end
end end
@ -30,7 +36,7 @@ RSpec.describe Gitlab::Database::Migrations::TestBackgroundRunner, :redis do
context 'finding pending background jobs' do context 'finding pending background jobs' do
it 'finds all the migrations' do it 'finds all the migrations' do
expect(described_class.new.traditional_background_migrations.to_a.size).to eq(5) expect(described_class.new(result_dir: result_dir).traditional_background_migrations.to_a.size).to eq(5)
end end
end end
@ -53,12 +59,28 @@ RSpec.describe Gitlab::Database::Migrations::TestBackgroundRunner, :redis do
end end
end end
def expect_recorded_migration_runs(migrations_to_runs)
migrations_to_runs.each do |migration, runs|
path = File.join(result_dir, migration.name.demodulize)
num_subdirs = Pathname(path).children.count(&:directory?)
expect(num_subdirs).to eq(runs)
end
end
def expect_migration_runs(migrations_to_run_counts)
expect_migration_call_counts(migrations_to_run_counts)
yield
expect_recorded_migration_runs(migrations_to_run_counts)
end
it 'runs the migration class correctly' do it 'runs the migration class correctly' do
calls = [] calls = []
define_background_migration(migration_name) do |i| define_background_migration(migration_name) do |i|
calls << i calls << i
end end
described_class.new.run_jobs(for_duration: 1.second) # Any time would work here as we do not advance time described_class.new(result_dir: result_dir).run_jobs(for_duration: 1.second) # Any time would work here as we do not advance time
expect(calls).to contain_exactly(1, 2, 3, 4, 5) expect(calls).to contain_exactly(1, 2, 3, 4, 5)
end end
@ -67,9 +89,9 @@ RSpec.describe Gitlab::Database::Migrations::TestBackgroundRunner, :redis do
travel(1.minute) travel(1.minute)
end end
expect_migration_call_counts(migration => 3) expect_migration_runs(migration => 3) do
described_class.new(result_dir: result_dir).run_jobs(for_duration: 3.minutes)
described_class.new.run_jobs(for_duration: 3.minutes) end
end end
context 'with multiple migrations to run' do context 'with multiple migrations to run' do
@ -90,12 +112,12 @@ RSpec.describe Gitlab::Database::Migrations::TestBackgroundRunner, :redis do
travel(2.minutes) travel(2.minutes)
end end
expect_migration_call_counts( expect_migration_runs(
migration => 2, # 1 minute jobs for 90 seconds, can finish the first and start the second migration => 2, # 1 minute jobs for 90 seconds, can finish the first and start the second
other_migration => 1 # 2 minute jobs for 90 seconds, past deadline after a single job other_migration => 1 # 2 minute jobs for 90 seconds, past deadline after a single job
) ) do
described_class.new(result_dir: result_dir).run_jobs(for_duration: 3.minutes)
described_class.new.run_jobs(for_duration: 3.minutes) end
end end
it 'does not give leftover time to extra migrations' do it 'does not give leftover time to extra migrations' do
@ -107,12 +129,13 @@ RSpec.describe Gitlab::Database::Migrations::TestBackgroundRunner, :redis do
other_migration = define_background_migration(other_migration_name) do other_migration = define_background_migration(other_migration_name) do
travel(1.minute) travel(1.minute)
end end
expect_migration_call_counts(
expect_migration_runs(
migration => 5, migration => 5,
other_migration => 2 other_migration => 2
) ) do
described_class.new(result_dir: result_dir).run_jobs(for_duration: 3.minutes)
described_class.new.run_jobs(for_duration: 3.minutes) end
end end
end end
end end

View file

@ -29,6 +29,8 @@ RSpec.describe API::ResourceAccessTokens do
token_ids = json_response.map { |token| token['id'] } token_ids = json_response.map { |token| token['id'] }
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(response).to match_response_schema('public_api/v4/resource_access_tokens')
expect(token_ids).to match_array(access_tokens.pluck(:id)) expect(token_ids).to match_array(access_tokens.pluck(:id))
end end
@ -131,6 +133,103 @@ RSpec.describe API::ResourceAccessTokens do
end end
end end
context "GET #{source_type}s/:id/access_tokens/:token_id" do
subject(:get_token) { get api("/#{source_type}s/#{resource_id}/access_tokens/#{token_id}", user) }
let_it_be(:project_bot) { create(:user, :project_bot) }
let_it_be(:token) { create(:personal_access_token, user: project_bot) }
let_it_be(:resource_id) { resource.id }
let_it_be(:token_id) { token.id }
before do
if source_type == 'project'
resource.add_maintainer(project_bot)
else
resource.add_owner(project_bot)
end
end
context "when the user has valid permissions" do
it "gets the #{source_type} access token from the #{source_type}" do
get_token
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/resource_access_token')
expect(json_response["name"]).to eq(token.name)
expect(json_response["scopes"]).to eq(token.scopes)
if source_type == 'project'
expect(json_response["access_level"]).to eq(resource.team.max_member_access(token.user.id))
else
expect(json_response["access_level"]).to eq(resource.max_member_access_for_user(token.user))
end
expect(json_response["expires_at"]).to eq(token.expires_at.to_date.iso8601)
end
context "when using #{source_type} access token to GET other #{source_type} access token" do
let_it_be(:other_project_bot) { create(:user, :project_bot) }
let_it_be(:other_token) { create(:personal_access_token, user: other_project_bot) }
let_it_be(:token_id) { other_token.id }
before do
resource.add_maintainer(other_project_bot)
end
it "gets the #{source_type} access token from the #{source_type}" do
get_token
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/resource_access_token')
expect(json_response["name"]).to eq(other_token.name)
expect(json_response["scopes"]).to eq(other_token.scopes)
if source_type == 'project'
expect(json_response["access_level"]).to eq(resource.team.max_member_access(other_token.user.id))
else
expect(json_response["access_level"]).to eq(resource.max_member_access_for_user(other_token.user))
end
expect(json_response["expires_at"]).to eq(other_token.expires_at.to_date.iso8601)
end
end
context "when attempting to get a non-existent #{source_type} access token" do
let_it_be(:token_id) { non_existing_record_id }
it "does not get the token, and returns 404" do
get_token
expect(response).to have_gitlab_http_status(:not_found)
expect(response.body).to include("Could not find #{source_type} access token with token_id: #{token_id}")
end
end
context "when attempting to get a token that does not belong to the specified #{source_type}" do
let_it_be(:resource_id) { other_resource.id }
it "does not get the token, and returns 404" do
get_token
expect(response).to have_gitlab_http_status(:not_found)
expect(response.body).to include("Could not find #{source_type} access token with token_id: #{token_id}")
end
end
end
context "when the user does not have valid permissions" do
let_it_be(:user) { user_non_priviledged }
it "returns 401" do
get_token
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
end
context "DELETE #{source_type}s/:id/access_tokens/:token_id", :sidekiq_inline do context "DELETE #{source_type}s/:id/access_tokens/:token_id", :sidekiq_inline do
subject(:delete_token) { delete api("/#{source_type}s/#{resource_id}/access_tokens/#{token_id}", user) } subject(:delete_token) { delete api("/#{source_type}s/#{resource_id}/access_tokens/#{token_id}", user) }

15
spec/support/fips.rb Normal file
View file

@ -0,0 +1,15 @@
# frozen_string_literal: true
# rubocop: disable RSpec/EnvAssignment
RSpec.configure do |config|
config.around(:each, :fips_mode) do |example|
prior_value = ENV["FIPS_MODE"]
ENV["FIPS_MODE"] = "true"
example.run
ENV["FIPS_MODE"] = prior_value
end
end
# rubocop: enable RSpec/EnvAssignment

View file

@ -0,0 +1,78 @@
# frozen_string_literal: true
RSpec.shared_examples 'milestone empty states' do
include Devise::Test::ControllerHelpers
let_it_be(:user) { build(:user) }
let(:empty_state) { 'Use milestones to track issues and merge requests over a fixed period of time' }
before do
assign(:projects, [])
allow(view).to receive(:current_user).and_return(user)
end
context 'with no milestones' do
before do
assign(:milestones, [])
assign(:milestone_states, { opened: 0, closed: 0, all: 0 })
render
end
it 'shows empty state' do
expect(rendered).to have_content(empty_state)
end
it 'does not show tabs or searchbar' do
expect(rendered).not_to have_link('Open')
expect(rendered).not_to have_link('Closed')
expect(rendered).not_to have_link('All')
end
end
context 'with no open milestones' do
before do
allow(view).to receive(:milestone_path).and_return("/milestones/1")
assign(:milestones, [])
assign(:milestone_states, { opened: 0, closed: 1, all: 1 })
end
it 'shows tabs and searchbar', :aggregate_failures do
render
expect(rendered).not_to have_content(empty_state)
expect(rendered).to have_link('Open')
expect(rendered).to have_link('Closed')
expect(rendered).to have_link('All')
end
it 'shows empty state' do
render
expect(rendered).to have_content('There are no open milestones')
end
end
context 'with no closed milestones' do
before do
allow(view).to receive(:milestone_path).and_return("/milestones/1")
allow(view).to receive(:params).and_return(state: 'closed')
assign(:milestones, [])
assign(:milestone_states, { opened: 1, closed: 0, all: 1 })
end
it 'shows tabs and searchbar', :aggregate_failures do
render
expect(rendered).not_to have_content(empty_state)
expect(rendered).to have_link('Open')
expect(rendered).to have_link('Closed')
expect(rendered).to have_link('All')
end
it 'shows empty state on closed milestones' do
render
expect(rendered).to have_content('There are no closed milestones')
end
end
end

View file

@ -538,6 +538,20 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout do
subject subject
end end
end end
describe '#sample_background_migrations' do
it 'delegates to the migration runner with a default sample duration' do
expect(::Gitlab::Database::Migrations::Runner).to receive_message_chain(:background_migrations, :run_jobs).with(for_duration: 30.minutes)
run_rake_task('gitlab:db:migration_testing:sample_background_migrations')
end
it 'delegates to the migration runner with a configured sample duration' do
expect(::Gitlab::Database::Migrations::Runner).to receive_message_chain(:background_migrations, :run_jobs).with(for_duration: 100.seconds)
run_rake_task('gitlab:db:migration_testing:sample_background_migrations', '[100]')
end
end
end end
describe '#execute_batched_migrations' do describe '#execute_batched_migrations' do

View file

@ -0,0 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'dashboard/milestones/index.html.haml' do
it_behaves_like 'milestone empty states'
end

View file

@ -0,0 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'groups/milestones/index.html.haml' do
it_behaves_like 'milestone empty states'
end

View file

@ -0,0 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'projects/milestones/index.html.haml' do
it_behaves_like 'milestone empty states'
end