summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-07-17 15:09:13 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-07-17 15:09:13 +0000
commit283fb71e02992b6687e3264d53bbc718b7567109 (patch)
tree0d81d9417cb9b6a0b5c519061e99567fe26ad5cd
parent518f1c923d6a11cc3dbc7b7c976ff8348bc1e08c (diff)
downloadgitlab-ce-283fb71e02992b6687e3264d53bbc718b7567109.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/reports.gitlab-ci.yml58
-rw-r--r--CHANGELOG.md488
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue12
-rw-r--r--app/assets/javascripts/incidents_settings/constants.js1
-rw-r--r--app/assets/javascripts/monitoring/components/refresh_button.vue15
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue16
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/index.js24
-rw-r--r--app/assets/javascripts/project_fork.js9
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js14
-rw-r--r--app/assets/stylesheets/pages/projects.scss21
-rw-r--r--app/controllers/explore/projects_controller.rb2
-rw-r--r--app/controllers/projects/environments_controller.rb1
-rw-r--r--app/controllers/projects/forks_controller.rb14
-rw-r--r--app/controllers/projects/merge_requests_controller.rb2
-rw-r--r--app/controllers/projects/metrics_dashboard_controller.rb1
-rw-r--r--app/controllers/projects/settings/operations_controller.rb4
-rw-r--r--app/helpers/application_settings_helper.rb3
-rw-r--r--app/models/application_setting.rb1
-rw-r--r--app/models/application_setting_implementation.rb3
-rw-r--r--app/models/release.rb10
-rw-r--r--app/models/wiki_page.rb16
-rw-r--r--app/services/incident_management/pager_duty/create_incident_issue_service.rb3
-rw-r--r--app/services/incident_management/pager_duty/process_webhook_service.rb3
-rw-r--r--app/services/projects/fork_service.rb4
-rw-r--r--app/views/profiles/preferences/show.html.haml2
-rw-r--r--app/views/projects/forks/_fork_button.html.haml40
-rw-r--r--app/views/projects/forks/new.html.haml11
-rw-r--r--changelogs/unreleased/227598-make-list-bullet-char-configurable.yml5
-rw-r--r--changelogs/unreleased/229158-remove-pagerduty_webhook-feature-flag.yml5
-rw-r--r--changelogs/unreleased/31176-wiki-page-size-validation.yml5
-rw-r--r--changelogs/unreleased/tags-controller-spec-debug.yml5
-rw-r--r--changelogs/unreleased/tchu-fix-explore-projects-controller-n-1.yml5
-rw-r--r--changelogs/unreleased/xanf-improve-fork-page-design.yml5
-rw-r--r--db/migrate/20200713141854_add_wiki_page_max_content_bytes_to_application_settings.rb9
-rw-r--r--db/post_migrate/20200608203426_set_proper_lock_version_indices.rb12
-rw-r--r--db/post_migrate/20200608212030_lock_version_cleanup_for_epics.rb4
-rw-r--r--db/post_migrate/20200608212435_lock_version_cleanup_for_merge_requests.rb4
-rw-r--r--db/post_migrate/20200608212549_lock_version_cleanup_for_issues.rb4
-rw-r--r--db/structure.sql2
-rw-r--r--doc/administration/high_availability/gitlab.md2
-rw-r--r--doc/administration/high_availability/sidekiq.md2
-rw-r--r--doc/administration/index.md6
-rw-r--r--doc/administration/instance_limits.md1
-rw-r--r--doc/administration/reference_architectures/5k_users.md1820
-rw-r--r--doc/administration/snippets/index.md17
-rw-r--r--doc/administration/wikis/index.md75
-rw-r--r--doc/api/settings.md9
-rw-r--r--doc/user/project/merge_requests/img/file_by_file_v13_2.pngbin0 -> 81874 bytes
-rw-r--r--doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md38
-rw-r--r--doc/user/project/repository/forking_workflow.md2
-rw-r--r--doc/user/project/repository/img/forking_workflow_choose_namespace.pngbin35084 -> 0 bytes
-rw-r--r--doc/user/project/repository/img/forking_workflow_choose_namespace_v13_2.pngbin0 -> 110382 bytes
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml4
-rw-r--r--lib/gitlab/usage_data/topology.rb6
-rw-r--r--locale/gitlab.pot3
-rw-r--r--package.json2
-rw-r--r--qa/qa/page/project/fork/new.rb4
-rw-r--r--spec/controllers/explore/projects_controller_spec.rb29
-rw-r--r--spec/controllers/projects/forks_controller_spec.rb18
-rw-r--r--spec/controllers/projects/tags_controller_spec.rb10
-rw-r--r--spec/features/projects/fork_spec.rb30
-rw-r--r--spec/frontend/incidents_settings/components/incidents_settings_tabs_spec.js4
-rw-r--r--spec/frontend/monitoring/components/refresh_button_spec.js18
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js20
-rw-r--r--spec/models/application_setting_spec.rb1
-rw-r--r--spec/models/release_spec.rb16
-rw-r--r--spec/models/wiki_page_spec.rb91
-rw-r--r--spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb99
-rw-r--r--spec/services/incident_management/pager_duty/process_webhook_service_spec.rb127
-rw-r--r--spec/services/projects/fork_service_spec.rb68
-rw-r--r--yarn.lock8
74 files changed, 2981 insertions, 400 deletions
diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml
index 228747ae8d3..b8617a14537 100644
--- a/.gitlab/ci/reports.gitlab-ci.yml
+++ b/.gitlab/ci/reports.gitlab-ci.yml
@@ -150,35 +150,35 @@ dependency_scanning:
## We need to duplicate this job's definition because it seems it's impossible to
## override an included `only.refs`.
## See https://gitlab.com/gitlab-org/gitlab/issues/31371.
-#dast:
-# extends:
-# - .default-retry
-# - .reports:rules:dast
-# # This is needed so that manual jobs with needs don't block the pipeline.
-# # See https://gitlab.com/gitlab-org/gitlab/-/issues/199979.
-# dependencies: ["review-deploy"]
-# stage: qa # GitLab-specific
-# image:
-# name: "registry.gitlab.com/gitlab-org/security-products/dast:$DAST_VERSION"
-# variables:
-# # To be done in a later iteration
-# # DAST_USERNAME: "root"
-# # DAST_USERNAME_FIELD: "user[login]"
-# # DAST_PASSWORD_FIELD: "user[passowrd]"
-# DAST_VERSION: 1
-# script:
-# - 'export DAST_WEBSITE="${DAST_WEBSITE:-$(cat environment_url.txt)}"'
-# # To be done in a later iteration
-# # - 'export DAST_AUTH_URL="${DAST_WEBSITE}/users/sign_in"'
-# # - 'export DAST_PASSWORD="${REVIEW_APPS_ROOT_PASSWORD}"'
-# - /analyze -t $DAST_WEBSITE
-# timeout: 4h
-# artifacts:
-# paths:
-# - gl-dast-report.json # GitLab-specific
-# reports:
-# dast: gl-dast-report.json
-# expire_in: 1 week # GitLab-specific
+# dast:
+# extends:
+# - .default-retry
+# - .reports:rules:dast
+# # This is needed so that manual jobs with needs don't block the pipeline.
+# # See https://gitlab.com/gitlab-org/gitlab/-/issues/199979.
+# dependencies: ["review-deploy"]
+# stage: qa # GitLab-specific
+# image:
+# name: "registry.gitlab.com/gitlab-org/security-products/dast:$DAST_VERSION"
+# variables:
+# # To be done in a later iteration
+# # DAST_USERNAME: "root"
+# # DAST_USERNAME_FIELD: "user[login]"
+# # DAST_PASSWORD_FIELD: "user[passowrd]"
+# DAST_VERSION: 1
+# script:
+# - 'export DAST_WEBSITE="${DAST_WEBSITE:-$(cat environment_url.txt)}"'
+# # To be done in a later iteration
+# # - 'export DAST_AUTH_URL="${DAST_WEBSITE}/users/sign_in"'
+# # - 'export DAST_PASSWORD="${REVIEW_APPS_ROOT_PASSWORD}"'
+# - /analyze -t $DAST_WEBSITE
+# timeout: 4h
+# artifacts:
+# paths:
+# - gl-dast-report.json # GitLab-specific
+# reports:
+# dast: gl-dast-report.json
+# expire_in: 1 week # GitLab-specific
# To be done in a later iteration: https://gitlab.com/gitlab-org/gitlab/issues/31160#note_278188255
# schedule:dast:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ac1050362ae..c4ace480119 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -44,6 +44,494 @@ entry.
- Periodically recompute project authorizations. !34071
+## 13.1.0 (2020-06-22)
+
+### Removed (4 changes, 2 of them are from the community)
+
+- Remove deprecated dashboard & group milestone pages. !13237
+- Removed UltraAuth integration for OmniAuth. !29330 (Kartikey Tanna)
+- Remove all search autocomplete for groups/projects/other. !31187
+- Remove temporary datepicker position fix as it is no longer required. !31836 (Arun Kumar Mohan)
+
+### Fixed (154 changes, 57 of them are from the community)
+
+- Fix 'Active' checkbox text in Pipeline Schedule form to be a label. !27054 (Jonston Chan)
+- Fix back button when switching MR tabs. !29862 (Lee Tickett)
+- Remove ability to scroll Issue while in Design View. !29881
+- Fix merge request note label URLs. !30428 (Lee Tickett)
+- Fix default path when creating project from group template. !30597 (Lee Tickett)
+- Group authorization refresh to consider shared groups. !31204
+- Fix group transfer service to deny moving group to its subgroup. !31495 (Abhisek Datta)
+- Fix issuable listings with any label filter. !31729
+- Move prepend to last in ee-app-services. !31838 (Rajendra Kadam)
+- Fallback to lowest visibility level in snippet visibility radio. !31847 (Jacopo Beschi @jacopo-beschi)
+- Add class stubs and fix leaky constant alert in query limit helper spec. !31949 (Rajendra Kadam)
+- Remove usage of spam constants in spec. !31959 (Rajendra Kadam)
+- Fix leaky constant issue in uninstall progress service check. !32036 (Rajendra Kadam)
+- Fix leaky constant issue in commit entity spec. !32039 (Rajendra Kadam)
+- Fix leaky constant issue in task completion status spec. !32043 (Rajendra Kadam)
+- Fix leaky constant issue in admin mode migration spec. !32074 (Rajendra Kadam)
+- Fix leaky constant issue in sidekiq middleware server metric spec. !32104 (Rajendra Kadam)
+- Fix leaky constant issue in sidekiq middleware client metric spec. !32108 (Rajendra Kadam)
+- Fix leaky constant issue in path regex spec. !32115 (Rajendra Kadam)
+- Fix leaky constant issue importer and cache headers spec. !32122 (Rajendra Kadam)
+- Fix leaky constant issue in relation factory spec. !32129 (Rajendra Kadam)
+- Fix leaky constant issue in test coverage spec. !32134 (Rajendra Kadam)
+- Prevent emails to user on expiry of impersonation token. !32140
+- Fix leaky constant issue in diff collection spec. !32163 (Rajendra Kadam)
+- Fix leaky constant issue in migration helpers, with lock retries and ignored cols spec. !32170 (Rajendra Kadam)
+- Fix leaky constant issue in factory spec. !32174 (Rajendra Kadam)
+- Fix leaky constant issue in creds factory spec. !32176 (Rajendra Kadam)
+- Use applogger in project import state file. !32182 (Rajendra Kadam)
+- Use applogger in project.rb. !32183 (Rajendra Kadam)
+- Use applogger in chat_team.rb. !32184 (Rajendra Kadam)
+- Use applogger in repository model. !32185 (Rajendra Kadam)
+- Use applogger in build and ssh host key. !32187 (Rajendra Kadam)
+- Use applogger in cache attrs and highest role ruby files. !32189 (Rajendra Kadam)
+- Use applogger in legacy project and namespace. !32190 (Rajendra Kadam)
+- Use applogger in base.rb. !32191 (Rajendra Kadam)
+- Use applogger in usage ping and webhook service. !32192 (Rajendra Kadam)
+- Use applogger in exclusive_lease_guard. !32194 (Rajendra Kadam)
+- Use applogger in groups destroy service and label create service. !32195 (Rajendra Kadam)
+- Use applogger in merge_service.rb. !32196 (Rajendra Kadam)
+- Use applogger in project create service and after import service. !32198 (Rajendra Kadam)
+- Use applogger in update stats service. !32200 (Rajendra Kadam)
+- Use applogger in base attachment service. !32201 (Rajendra Kadam)
+- Use applogger in export service. !32203 (Rajendra Kadam)
+- Use applogger in akismet service. !32205 (Rajendra Kadam)
+- Use applogger in file mover file. !32206 (Rajendra Kadam)
+- Use applogger in commit signature worker. !32207 (Rajendra Kadam)
+- Use applogger in delete user worker. !32209 (Rajendra Kadam)
+- Use applogger in email receiver worker. !32211 (Rajendra Kadam)
+- Use applogger in artifact worker. !32212 (Rajendra Kadam)
+- Use applogger in new note worker. !32213 (Rajendra Kadam)
+- Fix duplicate filename displayed in design todos. !32274 (Arun Kumar Mohan)
+- Add value length validations for instance level variable. !32303
+- Resolve image overflow at releases list panel. !32307
+- Clean up shared/tmp folder after Import/Export. !32326
+- Fix creating release evidence if release is created via UI. !32441
+- GraphQL hasNextPage and hasPreviousPage return correct values. !32476
+- Fix loading and empty state styling for alerts list. !32531
+- Resolve incorrect x-axis padding on the Environments Dashboard. !32533
+- Fix time_tracking help link. !32552
+- Don't display confidential note icon on confidential issue public notes. !32571
+- Update container expiration policy database defaults. !32600
+- Fix rendering of emojis in status tooltips. !32604
+- Hid copy contents button when blob has rendering error. !32632
+- Avoid refresh to show endedAt after mutation. !32636
+- Fix for metrics creation when saving MR. !32668
+- Skip the individual JIRA issues if failed to import vs failing the whole batch. !32673
+- Hide "Import from Jira" option from non-entitled users. !32685
+- Fix broken help link on operations settings page. !32722
+- Allow different in bulk editing issues. !32734
+- Fix whitespace changes overgrowing the diff container. !32774
+- Improve spacing and wrapping of group actions buttons and stats in group list view. !32786
+- Fix "Broadcast Messages" table overflow and button alignment. !32801
+- Fix 404 when downloading a non-archive artifact. !32811
+- Make commits author button confirm to Pajamas specs. !32821
+- Fix filename duplication in design notes in activity feeds. !32823 (Arun Kumar Mohan)
+- Prevent multiple Auto DevOps deployment jobs running concurrently when using manual rollout. !32824
+- Implement displaying downstream pipeline error details. !32844
+- Fix Runner heartbeats that results in considering them offline. !32851
+- Conan package registry support for the conan_export.tgz file. !32866
+- Fix plural message in account deletion section. !32868
+- Fix atomic processing bumping a lock_version. !32914
+- AsciiDoc: Add support for built-in alignment roles. !32928 (mnrvwl)
+- Fix a bug where some Vue apps would be unable to load when DAG tab is disabled. !32966
+- Fix undefined error in Gitlab::Git::Diff. !32967
+- Fix spelling error on Ci::RunnersFinder. !32985 (Arthur de Lapertosa Lisboa)
+- Fix polling for resource events. !33025
+- Fix broken CSS classes inside alert management list. !33038
+- Fix bug in snippet create mutation with non ActiveRecord errors. !33085
+- Fix overflow issue in MR and Issue comments. !33100
+- Fix alignment of button text on the Edit Release page. !33104
+- Deduplicate URL parameters when requesting merge request diffs which causes diffs load to fail. !33117
+- Fix tabbing through form fields in projects/new flow. !33209
+- Fix incorrect commit search results returned when searching with ref. !33216
+- Fix NoMethodError by using the correct method to report exceptions to Sentry. !33260
+- Fix KaTeX font paths. !33338
+- Resolve Fix Incomplete Kubernetes Cluster Status List. !33344
+- Fix auto-merge not running after discussions resolved. !33371
+- Fix bug in snippets updating only file_name or content. !33375
+- Fix invisible emoji modal on Set Status form when clicked the second time. !33398
+- vertically center action icon in the CI pipeline. !33427 (Nathanael Weber)
+- Wrap auto merge parameters update in database transaction. !33471
+- Return 404 response when redirecting request with invalid url. !33492
+- Fix ambiguous string concatenation on CleanupProjectsWithMissingNamespace. !33497
+- Fix snippet repository import edge cases. !33506
+- Rust CI template: Replace --all with --workspace on cargo test. !33517 (Markus Becker)
+- Make markdown textarea links tab-accessible. !33518
+- Pass hard delete option to snippets bulk destroy. !33520
+- Fix CI rules for ECS related jobs. !33527
+- Update GitLab Workhorse to v8.34.0. !33543
+- Fix snippet repository import fail with older export files. !33584
+- Web IDE: Create template files in the folder from which new file request was made. !33585 (Ashesh Vidyut)
+- Improve header acccessibility. !33603
+- Remove non migrated snippets from failed imports. !33621
+- Prevent duplicate issues when importing from CSV. !33626
+- Fix sidebar spacing for alert details. !33630
+- Fix linking alerts to created issues for the Generic alerts intergration. !33647
+- Resolve spacing ux debt on Release assets form field. !33684
+- Fix pagination link header. !33714 (Max Wittig)
+- Fix Value Stream Analytics summary when using non-english locale. !33717
+- Fix bug with variable substitution in alerts. !33772
+- Allow wiki pages with +<> characters in their title to be saved. !33803
+- Fix force_remove_source_branch not working in API. !33804
+- Fix prometheus alerts not being automatically created. !33806
+- Fix pagination for resource label events. !33821
+- Fix relative URL root in wiki_base_path. !33841
+- Return code navigation path for nil diff_refs. !33850
+- Record audit event when an admin creates a new SSH Key for a user via the API. !33859 (Rajendra Kadam)
+- Do not create duplicate issues for exising Alert Management alerts. !33860
+- Add link text to collapsed left sidebar links for screen readers. !33866
+- Update text in error tracking list error message. !33872
+- Adjust wrong column reference for ResetMergeStatus (background job). !33899
+- Fixed dashboard YAML file validaiton for files which do not contain object as root element. !33935
+- Fix design note scrolling. !33939
+- Update validates_hostname gem with support for more TLDs. !34010
+- Update wording of addMultipleToDiscussionWarning. !34088
+- Show all storages in settings. !34093
+- Set author as nullable in snippet GraphQL Type. !34135
+- Fix rendering of very long paths in merge request file tree. !34153
+- Remove not null constraint from events tables. !34190
+- Ensure we always generate a valid wiki event URL. !34191
+- Send information about attached files to the GraphQL mutation. !34221
+- Update issue limits template to use minutes. !34254
+- Add route for the lost-and-found group and update the route of orphaned projects. !34285
+- GraphQL - properly handle pagination of millisecond-precision timestamps. !34352
+- Fix 500 error in BlobController#delete. !34367
+- Updated Auto DevOps with a fix to delete PostgreSQL PVC on environment cleanup, a fix for multiline K8S_SECRET variables, updated Helm to 2.16.7 and glibc to 2.31. !34399 (verenion)
+- Fix issues with scroll on iOS / iPad OS. !34486
+- Fix order of integrations to be sorted alphabetically. !34501
+- Fix undefined method error. !34522
+- Use Keys::DestroyService for deleting an SSH key when an admin deletes a key via the API. !34535 (Rajendra Kadam)
+- Removed default artifact name for Terraform template. !34557
+- Footer system message fix.
+- Set experiementation cookie for GitLab domain only.
+- Add DS detection of build.gradle.kts.
+
+### Changed (76 changes, 5 of them are from the community)
+
+- Add a GraphQL endpoint to fetch Jira projects through its REST API. !28190
+- Change legends in monitor dashboards to tabular layout. !30131
+- Move pipelines routing under /-/ scope. !30730
+- Set markdown toolbar to use hyphens for lists. !31426
+- Use sprites for comment icons on Commits. !31696
+- Rate limit project export by user. !31719
+- Reorder diffs compare versions dropdowns. !31770 (Gilang Gumilar)
+- Enable the `in this group` action in the Search dropdown. !31939
+- Externalize i18n strings from ./app/views/shared/_promo.html.haml. !32109 (Gilang Gumilar)
+- Add Usage Ping count for all searches. !32111
+- Add tags_count to container registry api and controller. !32141
+- Externalize i18n strings from ./app/views/shared/milestones/_sidebar.html.haml. !32150 (Gilang Gumilar)
+- Externalize i18n strings from ./app/views/shared/milestones/_form_dates.html.haml. !32162 (Gilang Gumilar)
+- Improve Container Registry UI header. !32424
+- Added node size to cluster index. !32435
+- Update operations metrics settings title and description to make them general. !32494
+- Track merge_requests_users usage data. !32562
+- Adds cluster CPU and Memory to cluster index. !32601
+- Allow the snippet create service to accept an array of files. !32649
+- Move review related controllers/workers outside EE. !32663
+- Move the Members section from settings to the side nav for projects. !32667
+- Show more context in unresolved jump button. !32737
+- Exclude extra.server fields from exceptions_json.log. !32770
+- Improve new/unknown sign-in email styling. !32808
+- Allow the snippet update service to accept an array of files. !32832
+- Add new issue link to email notification header. !32833
+- Bump cluster-applications to 0.17.0, which updates Runner to 0.17.0 and Cilium to 1.7.4. !32931
+- Update artifacts section to show when an artifact is locked. !32992
+- Include tag count in the image repository list. !33027
+- Clean up gitlab-shell install-from-source path. !33057
+- Increase LFS token default time to 2 hours. !33140
+- Add explicit mention of Merge request in Slack message. !33152
+- Expose `release_links.type` via API. !33154
+- Add link_type column to release_links table. !33156
+- Move broadcast notification dismiss button to the top. !33174
+- Remove null constraint for JID in GroupImportState. !33181
+- Added provider type icon to cluster list. !33196
+- Remove search icon from Project find file button. !33198
+- Refine SAST language detection by frameworks. !33226
+- Render Merge request reference as link. !33248
+- Upgrade to Gitaly v13.1.0-rc1. !33302
+- Show disabled suggestion button with tooltip message. !33357
+- Add update validations to SnippetInputAction. !33379
+- Add snippet DB visibility check in spec. !33388 (Jacopo Beschi @jacopo-beschi)
+- Add Hugo logo to project templates. !33402
+- Add GitBook logo to project templates. !33403
+- Add GoMicro logo to project templates. !33404
+- Add Jekyll logo to project templates. !33405
+- Add Hexo logo to project templates. !33406
+- Rename Add Designs button. !33491
+- Add CPU, memory usage charts to self monitoring default dashboard. !33532
+- Add database migrations to design_management_designs.filename to enforce a 255 character limit, and modify any filenames that exceed that limit. !33565
+- Track Sentry error status updates with dedicated actions. !33623
+- Alert Managament: Change sorting order to have newest alerts first. !33642
+- Add blobs field to SnippetType in GraphQL. !33657
+- Format metrics column chart x axis dates. !33681
+- Style ToastUI contextual menus. !33719
+- Update Auto deploy image to v0.16.1, introducing support for AUTO_DEVOPS_DEPLOY_DEBUG. !33799
+- Add whether instance has Auto DevOps enabled to usage ping. !33811
+- Update local IP address and domain name allow list input label. !33812
+- Add date time format to the monitor stacked-column chart. !33814
+- Allow Tf Plan to genrate multiple reports. !33867
+- Remove async_merge_request_check_mergeability feature flag. !33917
+- Filter potentially-sensitive Sidekiq arguments from logs and Sentry. !33967
+- Update Static Site Editor toolbar to group inline-code and code-block buttons together. !34006
+- Set default values for SAST_EXCLUDED_PATHS and DS_EXCLUDED_PATHS. !34076
+- Add ability to filter self monitoring resource usage charts by instance name. !34084
+- Pick repository storage based on weight. !34095
+- Display error for YAML files that are too large. !34199
+- Change copy of webhooks / integration help text. !34301
+- Update board header icons. !34366
+- Show Redis instance in performance bar. !34377
+- Add secret detection template to Auto DevOps. !34467
+- Add allowed actions to snippet input action. !34499
+- Change from vendor specific to Gitlab. !34576
+- Assign alerts sidebar base.
+
+### Performance (19 changes, 1 of them is from the community)
+
+- Improve performance of commit search by limiting the number of results requested. !32260
+- Add GraphQL lookahead support. !32373
+- Update index_ci_builds_on_commit_id_and_artifacts_expireatandidpartial index for secret_detection. !32584
+- Add index on id and type for Snippets. !32885
+- Use build_stubbed to avoid interacting with the DB in todos helper specs. !32906 (Arun Kumar Mohan)
+- Optimize SQL queries on Milestone index page. !32953
+- Add build report results data model. !32991
+- Adjust condition for partial indexes on services table. !33044
+- Add index to issues and epics on last_edited_by_id. !33075
+- Fix preconnect typo in rel link. !33255
+- Add project_id, user_id, status, ref index to ci_pipelines. !33290
+- Move migration related to ci_builds to post_deployment. !33416
+- Reduce redundant queries for Search API users scope. !33795
+- Speed up boot time in production. !33929
+- Harden CI pipelines usage data queries with an index. !34045
+- Add partial index on locked merge requets. !34127
+- Lazy load commit_date and authored_date on Commit. !34181
+- Optimize container repository for groups query. !34364
+- Enable CI Atomic Processing by default.
+
+### Added (149 changes, 14 of them are from the community)
+
+- Add rake task to verify encrypted data through secrets. !21851
+- User can apply multiple suggestions at the same time. !22439 (Jesse Hall)
+- Resolve Add a button to assign users who have commented on an issue. !23883
+- Resolve Graph code coverage changes over time for a project. !26174
+- Add doc for custom validators in api styleguide. !26734 (Rajendra Kadam)
+- Add Scheduled Job for Monitoring Monitor Group Demo Environments. !27360
+- Add setting to allow merge on skipped pipeline. !27490 (Mathieu Parent)
+- Add dark theme (alpha). !28252
+- Show estimate on issues list. !28271 (Lee Tickett)
+- Make Fixed Email Notification Generally Available. !28338 (jacopo-beschi)
+- Add a link to the `renamed` viewer to fully expand the renamed file (if it's text). !28448
+- Focus and toggle metrics dashboard panels via keyboard. !28603
+- Remove `scoped_approval_rules` feature flag. !28864 (Lee Tickett)
+- Create Group import UI for creating new Groups. !29271
+- Add finder for group-level runners. !29283 (Arthur de Lapertosa Lisboa)
+- Allow customization of badge key_text and key_width. !29381 (Fabian Schneider @fabsrc)
+- Support Workhorse directly uploading files to S3. !29389
+- Add frontend support for multiline comments. !29516
+- Support first_name and last_name attributes in LDAP user sync. !29542
+- Add link to status page detail view for status page published issues. !30249
+- Add metrics dashboard name to document title. !30392
+- Backfill StatusPage::Published incidents and enable a publish quick action for EE. !30906
+- Add missing Merge Request fields. !30935
+- Show build status on branch list. !30948 (Lee Tickett)
+- Add mutation to create commits in GraphQL. !31102
+- Add GraphQL support for authored and assigned Merge Requests. !31227
+- Add usage data metrics for terraform states. !31280
+- Add usage data metrics for terraform reports. !31281
+- Add API endpoint for listing bridge jobs. !31370 (Abhijith Sivarajan)
+- SpamVerdictService can call external spam check endpoint. !31449
+- Move Admin note feature to GitLab Core. !31457 (Rajendra)
+- Add DAG serializer for pipelines controller. !31583
+- Save repository storages in application settings with weights. !31645
+- Add API endpoint for resource milestone events. !31720
+- Show import in progress screen for group imports. !31731
+- Add Verify/FailFast CI template. !31812
+- Improve Add/Remove Issue Labels API. !31864 (Lee Tickett)
+- Add mutation to create a merge request in GraphQL. !31867
+- Add warning popup for Elastic Stack update. !31972
+- Add API support for sharing groups with groups. !32008
+- Add the container expiration policy attribute to the project GraphQL type. !32100
+- Add GraphQL support for project and group labels. !32113
+- Add number of database calls to Prometheus metrics and logs for sidekiq and request. !32131
+- Filter pipelines by status. !32151
+- Filter pipelines based on url query params. !32230
+- Add metrics for Redis usage during Sidekiq job execution. !32265
+- Add filters to merge request fields. !32328
+- Support reading .editorconfig files inside of the Web IDE. !32378
+- [Frontend] Resolvable design discussions. !32399
+- Table index added to `metrics_dashboard_annotations` for future pruning of stale metrics Annotations for metrics dashboards are now checked for valid start and end dates. !32433
+- Enable GitLab-Flavored Markdown processing for design links. !32446
+- Filter Pipelines by Tag Name. !32470
+- Adds sorting by column to alert management list. !32478
+- Add project specific repository storage API. !32493
+- Adapt Limitable for system-wide features. !32574
+- Add application limits to instance level CI/CD variables. !32575
+- Add model for project level security auto-fix settings. !32577
+- Expose Jira imported issues count in GraphQL. !32580
+- Organize alerts by status tabs. !32582
+- Add note to ECS CI template. !32597
+- Add metrics for Redis usage during web requests. !32605
+- Add database and GraphQL support for alert assignees. !32609
+- Set fingerprints and increment events count for Alert Management alerts. !32613
+- Process stuck jira import jobs. !32643
+- Allow user to add custom links to their metrics dashboard panels. !32646
+- Add tags to experimental queue selector attributes. !32651
+- Allow generic endpoint to receive alerts from external Prometheus. !32676
+- Customize the Cloud Native Buildpack builder used with Auto Build. !32691
+- Add timezone display to alert based issue start time. !32702
+- Display dates on metrics dashboards in UTC time zone. !32746
+- Store Todo resolution method. !32753
+- Add experience_level to user_preferences. !32784
+- Remove metrics dashboard annotations attached to time periods older than two weeks. !32838
+- Monitor:Health metrics instrumenation. !32846
+- Adds PostHog as a CI/CD Managed Application. !32856
+- Groups API has top_level_only option to exclude subgroups. !32870
+- Create operations_feature_flags_issues table. !32876
+- Add api.js methods to update issues and merge requests. !32893
+- Render user-defined links in dashboard yml file on metrics dashboard. !32895
+- Add accessibility report MR widget. !32902
+- Add a GraphQL mutation for toggling the resolved state of a Discussion. !32934
+- Add container expiration policy objects to the GraphQL API. !32944
+- Don't hide Commit tab in Web IDE when there are no changes yet. !32979
+- Add column for alert slack notifications. !33017
+- Add ability to insert an image via SSE. !33029
+- Add user root query to GraphQL API. !33041
+- Adds groupMembership and projectMembership to GraphQL API. !33049
+- Alerts list pagination. !33073
+- Add ApplicationSetting ui changes for repository_storages_weighted. !33096
+- Display confirmation modal when user exits SSE and there are unsaved changes. !33103
+- Add column dashboard_timezone to project_metrics_setting. !33120
+- Allow the assignment of alerts to users from the alert detail view. !33122
+- Add solarized dark for Web IDE. !33148
+- Add support for artifacts/exclude configuration. !33170
+- Add root users query to GraphQL API. !33195
+- Added validation for YAML files with metrics dashboard definitions. !33202
+- Create issue from alert. !33213
+- Add max import file size option. !33215 (Roger Meier)
+- Add system note when assigning user to alert. !33217
+- Add count of alerts from all sources to usage ping. !33220
+- Add button to create an issue from an alert management alert. !33221
+- Add more detail to alert integration settings description. !33244
+- Add Evidence to Releases GraphQL endpoint. !33254
+- Add support for pasting images in the Web IDE. !33256
+- Add ProjectAccessToken table. !33272
+- Automatically resolve alert when associated issue closes. !33278
+- Add `link_type` to `ReleaseLink` GraphQL type. !33386
+- Add members to project graphQL endpoint. !33418
+- Update Static Site Editor WYSIWYG mode to hide front matter. !33441
+- Added delete action for Dashboard Annotations in GraphQL. !33468
+- Create graphQL endpoint for Jira users import. !33501
+- Support IAP protected prometheus installations. !33508
+- New instance-level variables UI. !33510
+- Provide `__range` variable for Prometheus queries. !33521
+- Add support for `git filter-repo` to repository cleanup. !33576
+- Close open reply input fields in the design view sidebar when leaving a new comment. !33587
+- Add dashboard schema validation warnings as metrics dashboard GraphQL field. !33592
+- Add time range to user-defined links in metrics dashboard. !33663
+- Increase events count for Prometheus alerts. !33706
+- Track pod logs refresh action. !33802
+- Add secret detection template. !33869
+- Add DAG visualization MVC. !33958
+- Introduce a feature flag for Vue-based UI for all import providers. !33980
+- Add sticky title on Issue pages. !33983
+- Allow Release asset links to be associated with a type. !33998
+- Support user-defined Grafana links in metrics dashboard. !34003
+- Adds AWS guidance to CI/CD > Add Variable modal. !34009
+- Show custom attributes within Admin Pages. !34017 (Roger Meier)
+- Enable Slack notifications for alerts. !34038
+- Container expiration policy regular expressions are now validated. !34063
+- Add todo when alert is assigned to a user. !34104
+- Track merge requests submitted by Static Site Editor. !34105
+- Turn off alert issue creation by default. !34107
+- Add detailed logs of each Redis instance usage during job execution and web requests. !34110
+- Add API to schedule project repository storage moves. !34119
+- Add validation step on backend for metrics dashboard links. !34204
+- Track when Static Site Editor is initialized. !34215
+- Bring SAST to Core - brakeman. !34217
+- Mask key comments when exposing SSH/Deploy Keys via the API. !34255
+- Convert `:release` yaml to `release-cli` commands. !34261
+- Validate regex before sending them to CleanupContainerRepositoryWorker. !34282
+- Add secret_detection to DOWNLOADABLE_TYPES. !34313
+- Enable ability to assign alerts to users with corresponding system notes and todos. !34360
+- Enable CI Inheriting Env Variables feature. !34495
+- Show tooltip on error detail page when hovering over dates. !34506
+- Add native code intelligence. !34542
+- Bump cluster-applications version to v0.20.0. !34569
+- Add search argument for AlertStatusCountsResolver. !34596
+- Allow CI_JOB_TOKEN for authenticating to the Terraform state API. !34618
+
+### Other (65 changes, 36 of them are from the community)
+
+- Improve fast-forward merge is not possible message. !22834 (Ben Bodenmiller)
+- Remove unused WAF indexes from CI variables. !30021
+- Update the visual design of badges in some areas. !31646
+- Extract featurable concern from ProjectFeature. !31700 (Alexander Randa)
+- Remove update function logic from list model. !31900 (nuwe1)
+- Remove nextpage function logic from list model. !31904 (nuwe1)
+- Squash database migrations prior to 2019 into one. !31936
+- Update deprecated slot syntax in app/assets/javascripts/reports/components/grouped_test_reports_app.vue. !31975 (Gilang Gumilar)
+- Replace slot syntax for Vue 3 migration. !31987 (gaslan)
+- Update deprecated slot syntax in ./app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue. !31994 (Gilang Gumilar)
+- Update deprecated slot syntax in ./app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue. !31995 (Gilang Gumilar)
+- Update deprecated slot syntax in ./app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue. !32010 (Gilang Gumilar)
+- Update deprecated slot syntax in ./app/assets/javascripts/environments/components/environments_app.vue. !32011 (Gilang Gumilar)
+- Remove setLoadingState logic from issue model. !32226 (nuwe1)
+- Remove addAssignee logic from issue model. !32231 (nuwe1)
+- Remove addLabel Logic from issue models. !32233 (nuwe1)
+- Remove addMilestone logic from issue model. !32235 (nuwe1)
+- Remove destroy function logic from list model. !32237 (nuwe1)
+- Remove findAssignee logic from issue model. !32238 (nuwe1)
+- Remove findLabel logic from issue model. !32239 (nuwe1)
+- Remove findIssue logic from list model. !32241 (nuwe1)
+- Remove moveIssue logic from list model. !32242 (nuwe1)
+- Remove newIssue logic from list model. !32244 (nuwe1)
+- Remove removeAllAssignees logic from issue model. !32247 (nuwe1)
+- Remove removeAssignee logic from issue model. !32248 (nuwe1)
+- Clarify verbiage for stuck job messages. !32250
+- Remove removeLabel logic from issue model. !32251 (nuwe1)
+- Remove removeLabels logic from issue model. !32252 (nuwe1)
+- Remove removeMilestone logic from issue model. !32253 (nuwe1)
+- Remove removeMultipleIssues logic from list model. !32254 (nuwe1)
+- Remove setFetchingState logic from issue model. !32255 (nuwe1)
+- Remove updateData logic from issue model. !32256 (nuwe1)
+- Update U2F docs for Firefox 67+. !32289 (Takuya Noguchi)
+- Update alert management mobile table alignment. !32295
+- Include available instance memory in usage ping. !32315
+- Moves merge request reviews into Core. !32558
+- Update GitLab Runner Helm Chart to 0.17.0. !32634
+- Add snowplow tracking for logs page. !32704
+- Extend "Remember me" token after each login. !32730
+- Assign alerts sidebar container fix. !32743
+- Add anchor for creating a branch. !32745
+- Tidy. !32759 (Lee Tickett)
+- Less verbose JiraService error logs. !32847
+- Reduced padding and increased emphasis of titles within the epic tree. !32873
+- Remove obsolete users.ghost column. !32957
+- Move NoPrimary table def to last context in spec. !33015 (Rajendra Kadam)
+- Document github rate limit behavior. !33090
+- Added build_id column to requirements_management_test_reports table. !33184
+- Add version history information on U2F support. !33229 (Takuya Noguchi)
+- Convert IP spoofing errors into client errors. !33280
+- Update docs to reflect move web IDE Terminal and file sync to Core. !33419
+- Add hovering icon for sorting columns on alert management list. !33429
+- Avoid javascript for omniauth logins. !33459 (Diego Louzán)
+- Add opacity transition to active design discussion pins. !33493
+- Update GitLab Runner Helm Chart to 0.17.1. !33504
+- Make project selector in various dashboard more translatable. !33771
+- Update Workhorse to v8.35.0. !33817
+- Remove FF hide_token_from_runners_api. !33947
+- Bump omniauth_openid_connect to 0.3.5. !34030 (Roger Meier)
+- Specify tiers for SAML SSO at self-hosted plans. !34040 (Takuya Noguchi)
+- Backfill failed imported snippet repositories. !34052
+- Use GitLab SVG icon for file attacher action. !34196
+- Add GraphQL snippet FileInputType. !34442
+- Update red hex values to match GitLab UI. !34544
+- Remove removeIssue logic from list model. (nuwe1)
+
+
## 13.0.10 (2020-07-09)
### Fixed (1 change)
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 157f6ccd96d..cfe2f8cbb3f 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-9c3d907fa8f50a8ed6a87279631cc4c729b91d3f
+9e6f5f40e6eb44655b6acfd5dc222af04333a4f2
diff --git a/app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue b/app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue
index 0623c275c5a..7411c0ffe0d 100644
--- a/app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue
+++ b/app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue
@@ -2,7 +2,6 @@
import { GlButton, GlTabs, GlTab } from '@gitlab/ui';
import AlertsSettingsForm from './alerts_form.vue';
import PagerDutySettingsForm from './pagerduty_form.vue';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { INTEGRATION_TABS_CONFIG, I18N_INTEGRATION_TABS } from '../constants';
export default {
@@ -13,17 +12,8 @@ export default {
AlertsSettingsForm,
PagerDutySettingsForm,
},
- mixins: [glFeatureFlagMixin()],
tabs: INTEGRATION_TABS_CONFIG,
i18n: I18N_INTEGRATION_TABS,
- methods: {
- isFeatureFlagEnabled(tab) {
- if (tab.featureFlag) {
- return this.glFeatures[tab.featureFlag];
- }
- return true;
- },
- },
};
</script>
@@ -49,7 +39,7 @@ export default {
<gl-tabs>
<gl-tab
v-for="(tab, index) in $options.tabs"
- v-if="tab.active && isFeatureFlagEnabled(tab)"
+ v-if="tab.active"
:key="`${tab.title}_${index}`"
:title="tab.title"
>
diff --git a/app/assets/javascripts/incidents_settings/constants.js b/app/assets/javascripts/incidents_settings/constants.js
index b443c237f0f..e68198f84e0 100644
--- a/app/assets/javascripts/incidents_settings/constants.js
+++ b/app/assets/javascripts/incidents_settings/constants.js
@@ -11,7 +11,6 @@ export const INTEGRATION_TABS_CONFIG = [
title: s__('IncidentSettings|PagerDuty integration'),
component: 'PagerDutySettingsForm',
active: true,
- featureFlag: 'pagerdutyWebhook',
},
{
title: s__('IncidentSettings|Grafana integration'),
diff --git a/app/assets/javascripts/monitoring/components/refresh_button.vue b/app/assets/javascripts/monitoring/components/refresh_button.vue
index 5481806c3e0..31092a26048 100644
--- a/app/assets/javascripts/monitoring/components/refresh_button.vue
+++ b/app/assets/javascripts/monitoring/components/refresh_button.vue
@@ -10,6 +10,7 @@ import {
GlNewDropdownDivider,
GlTooltipDirective,
} from '@gitlab/ui';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
const makeInterval = (length = 0, unit = 's') => {
const shortLabel = `${length}${unit}`;
@@ -53,6 +54,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
+ mixins: [glFeatureFlagsMixin()],
data() {
return {
refreshInterval: null,
@@ -60,6 +62,12 @@ export default {
};
},
computed: {
+ disableMetricDashboardRefreshRate() {
+ // Can refresh rates impact performance?
+ // Add "negative" feature flag called `disable_metric_dashboard_refresh_rate`
+ // See more at: https://gitlab.com/gitlab-org/gitlab/-/issues/229831
+ return this.glFeatures.disableMetricDashboardRefreshRate;
+ },
dropdownText() {
return this.refreshInterval?.shortLabel ?? __('Off');
},
@@ -142,7 +150,12 @@ export default {
icon="retry"
@click="refresh"
/>
- <gl-new-dropdown v-gl-tooltip :title="s__('Metrics|Set refresh rate')" :text="dropdownText">
+ <gl-new-dropdown
+ v-if="!disableMetricDashboardRefreshRate"
+ v-gl-tooltip
+ :title="s__('Metrics|Set refresh rate')"
+ :text="dropdownText"
+ >
<gl-new-dropdown-item
:is-check-item="true"
:is-checked="refreshInterval === null"
diff --git a/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue b/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue
index 792c2f3db34..b4816fa2cb3 100644
--- a/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue
+++ b/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue
@@ -35,7 +35,7 @@ export default {
},
},
data() {
- return { namespaces: null };
+ return { namespaces: null, isForking: false };
},
computed: {
@@ -67,6 +67,13 @@ export default {
},
},
+ methods: {
+ fork() {
+ this.isForking = true;
+ this.$refs.form.submit();
+ },
+ },
+
i18n: {
hasReachedProjectLimitMessage: __('You have reached your project limit'),
insufficientPermissionsMessage: __(
@@ -124,14 +131,17 @@ export default {
>
<template v-else>
<div ref="selectButtonWrapper">
- <form method="POST" :action="group.fork_path">
+ <form ref="form" method="POST" :action="group.fork_path">
<input type="hidden" name="authenticity_token" :value="$options.csrf.token" />
<gl-button
type="submit"
- class="gl-h-7 gl-text-decoration-none!"
+ class="gl-h-7"
:data-qa-name="group.full_name"
+ category="secondary"
variant="success"
:disabled="isSelectButtonDisabled"
+ :loading="isForking"
+ @click="fork"
>{{ __('Select') }}</gl-button
>
</form>
diff --git a/app/assets/javascripts/pages/projects/forks/new/index.js b/app/assets/javascripts/pages/projects/forks/new/index.js
index d80e27e9156..79485859738 100644
--- a/app/assets/javascripts/pages/projects/forks/new/index.js
+++ b/app/assets/javascripts/pages/projects/forks/new/index.js
@@ -1,3 +1,23 @@
-import ProjectFork from '~/project_fork';
+import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import ForkGroupsList from './components/fork_groups_list.vue';
-document.addEventListener('DOMContentLoaded', () => new ProjectFork());
+document.addEventListener('DOMContentLoaded', () => {
+ const mountElement = document.getElementById('fork-groups-mount-element');
+
+ const { endpoint, canCreateProject } = mountElement.dataset;
+
+ const hasReachedProjectLimit = !parseBoolean(canCreateProject);
+
+ return new Vue({
+ el: mountElement,
+ render(h) {
+ return h(ForkGroupsList, {
+ props: {
+ endpoint,
+ hasReachedProjectLimit,
+ },
+ });
+ },
+ });
+});
diff --git a/app/assets/javascripts/project_fork.js b/app/assets/javascripts/project_fork.js
deleted file mode 100644
index f5cd1c3cc3e..00000000000
--- a/app/assets/javascripts/project_fork.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import $ from 'jquery';
-
-export default () => {
- $('.js-fork-thumbnail').on('click', function forkThumbnailClicked() {
- if ($(this).hasClass('disabled')) return false;
-
- return $('.js-fork-content').toggleClass('hidden');
- });
-};
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js
index ed04765c871..3331f4fb20d 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js
@@ -1,7 +1,9 @@
+/* eslint-disable @gitlab/require-i18n-strings */
import { defaults, repeat } from 'lodash';
const DEFAULTS = {
subListIndentSpaces: 4,
+ unorderedListBulletChar: '-',
};
const countIndentSpaces = text => {
@@ -11,9 +13,12 @@ const countIndentSpaces = text => {
};
const buildHTMLToMarkdownRender = (baseRenderer, formattingPreferences = {}) => {
- const { subListIndentSpaces } = defaults(formattingPreferences, DEFAULTS);
- // eslint-disable-next-line @gitlab/require-i18n-strings
+ const { subListIndentSpaces, unorderedListBulletChar } = defaults(
+ formattingPreferences,
+ DEFAULTS,
+ );
const sublistNode = 'LI OL, LI UL';
+ const unorderedListItemNode = 'UL LI';
return {
TEXT_NODE(node) {
@@ -47,6 +52,11 @@ const buildHTMLToMarkdownRender = (baseRenderer, formattingPreferences = {}) =>
return reindentedList;
},
+ [unorderedListItemNode](node, subContent) {
+ const baseResult = baseRenderer.convert(node, subContent);
+
+ return baseResult.replace(/^(\s*)([*|-])/, `$1${unorderedListBulletChar}`);
+ },
};
};
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 438f6c2546e..a1a9489e659 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -472,17 +472,9 @@
margin-right: auto;
}
- a {
- display: block;
- width: 100%;
- height: 100%;
- padding-top: $gl-padding;
- text-decoration: none;
-
- &.disabled {
- opacity: 0.3;
- cursor: not-allowed;
- }
+ a.disabled {
+ opacity: 0.3;
+ cursor: not-allowed;
}
}
@@ -1538,3 +1530,10 @@ pre.light-well {
}
}
}
+
+@include media-breakpoint-down(xs) {
+ .fork-filtered-search {
+ width: 100%;
+ margin: $gl-spacing-scale-2 0;
+ }
+}
diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb
index f1f41e67a4c..b3fa089a712 100644
--- a/app/controllers/explore/projects_controller.rb
+++ b/app/controllers/explore/projects_controller.rb
@@ -80,7 +80,7 @@ class Explore::ProjectsController < Explore::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def preload_associations(projects)
- projects.includes(:route, :creator, :group, namespace: [:route, :owner])
+ projects.includes(:route, :creator, :group, :project_feature, namespace: [:route, :owner])
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb
index d5da24a76de..99ec100e4c9 100644
--- a/app/controllers/projects/environments_controller.rb
+++ b/app/controllers/projects/environments_controller.rb
@@ -13,6 +13,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController
authorize_metrics_dashboard!
push_frontend_feature_flag(:prometheus_computed_alerts)
+ push_frontend_feature_flag(:disable_metric_dashboard_refresh_rate)
end
before_action :authorize_read_environment!, except: [:metrics, :additional_metrics, :metrics_dashboard, :metrics_redirect]
before_action :authorize_create_environment!, only: [:new, :create]
diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb
index b93f6384e0c..41631aea620 100644
--- a/app/controllers/projects/forks_controller.rb
+++ b/app/controllers/projects/forks_controller.rb
@@ -36,7 +36,19 @@ class Projects::ForksController < Projects::ApplicationController
end
def new
- @namespaces = fork_service.valid_fork_targets - [project.namespace]
+ respond_to do |format|
+ format.html do
+ @own_namespace = current_user.namespace if fork_service.valid_fork_targets.include?(current_user.namespace)
+ @project = project
+ end
+
+ format.json do
+ namespaces = fork_service.valid_fork_targets - [current_user.namespace, project.namespace]
+ render json: {
+ namespaces: ForkNamespaceSerializer.new.represent(namespaces, project: project, current_user: current_user)
+ }
+ end
+ end
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index e65e5531b88..5d4514be838 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -84,7 +84,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
@issuable_sidebar = serializer.represent(@merge_request, serializer: 'sidebar')
@current_user_data = UserSerializer.new(project: @project).represent(current_user, {}, MergeRequestUserEntity).to_json
@show_whitespace_default = current_user.nil? || current_user.show_whitespace_in_diffs
- @file_by_file_default = Feature.enabled?(:view_diffs_file_by_file) && current_user&.view_diffs_file_by_file
+ @file_by_file_default = Feature.enabled?(:view_diffs_file_by_file, default_enabled: true) && current_user&.view_diffs_file_by_file
@coverage_path = coverage_reports_project_merge_request_path(@project, @merge_request, format: :json) if @merge_request.has_coverage_reports?
@endpoint_metadata_url = endpoint_metadata_url(@project, @merge_request)
diff --git a/app/controllers/projects/metrics_dashboard_controller.rb b/app/controllers/projects/metrics_dashboard_controller.rb
index 235ee1dfbf2..a7edfea5c09 100644
--- a/app/controllers/projects/metrics_dashboard_controller.rb
+++ b/app/controllers/projects/metrics_dashboard_controller.rb
@@ -9,6 +9,7 @@ module Projects
before_action :authorize_metrics_dashboard!
before_action do
push_frontend_feature_flag(:prometheus_computed_alerts)
+ push_frontend_feature_flag(:disable_metric_dashboard_refresh_rate)
end
def show
diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb
index d7a6f1b0139..5b12bd000d8 100644
--- a/app/controllers/projects/settings/operations_controller.rb
+++ b/app/controllers/projects/settings/operations_controller.rb
@@ -6,10 +6,6 @@ module Projects
before_action :authorize_admin_operations!
before_action :authorize_read_prometheus_alerts!, only: [:reset_alerting_token]
- before_action do
- push_frontend_feature_flag(:pagerduty_webhook, project)
- end
-
respond_to :json, only: [:reset_alerting_token, :reset_pagerduty_token]
helper_method :error_tracking_setting
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index aa118a9bc45..fdea17c2075 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -327,7 +327,8 @@ module ApplicationSettingsHelper
:project_download_export_limit,
:group_import_limit,
:group_export_limit,
- :group_download_export_limit
+ :group_download_export_limit,
+ :wiki_page_max_content_bytes
]
end
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 425a0e05c7d..4607f291a26 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -272,6 +272,7 @@ class ApplicationSetting < ApplicationRecord
numericality: { greater_than_or_equal_to: 0 }
validates :snippet_size_limit, numericality: { only_integer: true, greater_than: 0 }
+ validates :wiki_page_max_content_bytes, numericality: { only_integer: true, greater_than: 0 }
validates :email_restrictions, untrusted_regexp: true
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index c489d11d462..815a570f77a 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -164,7 +164,8 @@ module ApplicationSettingImplementation
project_download_export_limit: 1,
group_import_limit: 6,
group_export_limit: 6,
- group_download_export_limit: 1
+ group_download_export_limit: 1,
+ wiki_page_max_content_bytes: 50.megabytes
}
end
diff --git a/app/models/release.rb b/app/models/release.rb
index a0245105cd9..4c9d89105d7 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -18,12 +18,10 @@ class Release < ApplicationRecord
has_many :milestones, through: :milestone_releases
has_many :evidences, inverse_of: :release, class_name: 'Releases::Evidence'
- default_value_for :released_at, allows_nil: false do
- Time.zone.now
- end
-
accepts_nested_attributes_for :links, allow_destroy: true
+ before_create :set_released_at
+
validates :project, :tag, presence: true
validates_associated :milestone_releases, message: -> (_, obj) { obj[:value].map(&:errors).map(&:full_messages).join(",") }
@@ -90,6 +88,10 @@ class Release < ApplicationRecord
repository.find_tag(tag)
end
end
+
+ def set_released_at
+ self.released_at ||= created_at
+ end
end
Release.prepend_if_ee('EE::Release')
diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb
index 3dc90edb331..6a4b4472a03 100644
--- a/app/models/wiki_page.rb
+++ b/app/models/wiki_page.rb
@@ -65,6 +65,7 @@ class WikiPage
validates :title, presence: true
validates :content, presence: true
validate :validate_path_limits, if: :title_changed?
+ validate :validate_content_size_limit, if: :content_changed?
# The GitLab Wiki instance.
attr_reader :wiki
@@ -282,6 +283,10 @@ class WikiPage
end
end
+ def content_changed?
+ attributes[:content] != page&.text_data
+ end
+
# Updates the current @attributes hash by merging a hash of params
def update_attributes(attrs)
attrs[:title] = process_title(attrs[:title]) if attrs[:title].present?
@@ -391,4 +396,15 @@ class WikiPage
})
end
end
+
+ def validate_content_size_limit
+ current_value = raw_content.to_s.bytesize
+ max_size = Gitlab::CurrentSettings.wiki_page_max_content_bytes
+ return if current_value <= max_size
+
+ errors.add(:content, _('is too long (%{current_value}). The maximum size is %{max_size}.') % {
+ current_value: ActiveSupport::NumberHelper.number_to_human_size(current_value),
+ max_size: ActiveSupport::NumberHelper.number_to_human_size(max_size)
+ })
+ end
end
diff --git a/app/services/incident_management/pager_duty/create_incident_issue_service.rb b/app/services/incident_management/pager_duty/create_incident_issue_service.rb
index ee0feb49e0d..c0c07f39708 100644
--- a/app/services/incident_management/pager_duty/create_incident_issue_service.rb
+++ b/app/services/incident_management/pager_duty/create_incident_issue_service.rb
@@ -40,8 +40,7 @@ module IncidentManagement
end
def webhook_available?
- Feature.enabled?(:pagerduty_webhook, project) &&
- incident_management_setting.pagerduty_active?
+ incident_management_setting.pagerduty_active?
end
def forbidden
diff --git a/app/services/incident_management/pager_duty/process_webhook_service.rb b/app/services/incident_management/pager_duty/process_webhook_service.rb
index 5dd3186694a..fd8252f75fb 100644
--- a/app/services/incident_management/pager_duty/process_webhook_service.rb
+++ b/app/services/incident_management/pager_duty/process_webhook_service.rb
@@ -39,8 +39,7 @@ module IncidentManagement
end
def webhook_setting_active?
- Feature.enabled?(:pagerduty_webhook, project) &&
- incident_management_setting.pagerduty_active?
+ incident_management_setting.pagerduty_active?
end
def valid_token?(token)
diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb
index 6ac53b15ef9..bb660d47887 100644
--- a/app/services/projects/fork_service.rb
+++ b/app/services/projects/fork_service.rb
@@ -14,10 +14,10 @@ module Projects
@valid_fork_targets ||= ForkTargetsFinder.new(@project, current_user).execute
end
- def valid_fork_target?
+ def valid_fork_target?(namespace = target_namespace)
return true if current_user.admin?
- valid_fork_targets.include?(target_namespace)
+ valid_fork_targets.include?(namespace)
end
private
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index 659b3066603..bc1f2cb3072 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -70,7 +70,7 @@
= f.check_box :show_whitespace_in_diffs, class: 'form-check-input'
= f.label :show_whitespace_in_diffs, class: 'form-check-label' do
= s_('Preferences|Show whitespace changes in diffs')
- - if Feature.enabled?(:view_diffs_file_by_file)
+ - if Feature.enabled?(:view_diffs_file_by_file, default_enabled: true)
.form-group.form-check
= f.check_box :view_diffs_file_by_file, class: 'form-check-input'
= f.label :view_diffs_file_by_file, class: 'form-check-label' do
diff --git a/app/views/projects/forks/_fork_button.html.haml b/app/views/projects/forks/_fork_button.html.haml
index eec02a50b85..dd49e8bdb4b 100644
--- a/app/views/projects/forks/_fork_button.html.haml
+++ b/app/views/projects/forks/_fork_button.html.haml
@@ -1,26 +1,20 @@
- avatar = namespace_icon(namespace, 100)
- can_create_project = current_user.can?(:create_projects, namespace)
-- if forked_project = namespace.find_fork_of(@project)
- .bordered-box.fork-thumbnail.text-center.gl-ml-3.gl-mr-3.gl-mt-3.gl-mb-3.forked
- = link_to project_path(forked_project) do
- - if /no_((\w*)_)*avatar/.match(avatar)
- = group_icon(namespace, class: "avatar rect-avatar s100 identicon mx-auto")
- - else
- .avatar-container.s100.mx-auto
- = image_tag(avatar, class: "avatar s100")
- %h5.gl-mt-3
- = namespace.human_name
-- else
- .bordered-box.fork-thumbnail.text-center.gl-ml-3.gl-mr-3.gl-mt-3.gl-mb-3{ class: ("disabled" unless can_create_project) }
- = link_to project_forks_path(@project, namespace_key: namespace.id),
- method: "POST",
- class: ("disabled has-tooltip" unless can_create_project),
- title: (_('You have reached your project limit') unless can_create_project) do
- - if /no_((\w*)_)*avatar/.match(avatar)
- = group_icon(namespace, class: "avatar rect-avatar s100 identicon mx-auto")
- - else
- .avatar-container.s100.mx-auto
- = image_tag(avatar, class: "avatar s100")
- %h5.gl-mt-3{ data: { qa_selector: 'fork_namespace_content', qa_name: namespace.human_name } }
- = namespace.human_name
+.bordered-box.fork-thumbnail.text-center.gl-m-3{ class: ("disabled" unless can_create_project) }
+ - if /no_((\w*)_)*avatar/.match(avatar)
+ = group_icon(namespace, class: "avatar rect-avatar s100 identicon mx-auto")
+ - else
+ .avatar-container.s100.mx-auto.gl-mt-5
+ = image_tag(avatar, class: "avatar s100")
+ %h5.gl-mt-3
+ = namespace.human_name
+ - if forked_project = namespace.find_fork_of(@project)
+ = link_to _("Go to project"), project_path(forked_project), class: "btn"
+ - else
+ %div{ class: ('has-tooltip' unless can_create_project),
+ title: (_('You have reached your project limit') unless can_create_project) }
+ = link_to _("Select"), project_forks_path(@project, namespace_key: namespace.id),
+ data: { qa_selector: 'fork_namespace_button', qa_name: namespace.human_name },
+ method: "POST",
+ class: ["btn btn-success", ("disabled" unless can_create_project)]
diff --git a/app/views/projects/forks/new.html.haml b/app/views/projects/forks/new.html.haml
index 887081d0f35..daac118d88e 100644
--- a/app/views/projects/forks/new.html.haml
+++ b/app/views/projects/forks/new.html.haml
@@ -7,15 +7,10 @@
%p
= _("A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project.").html_safe
.col-lg-9
- - if @namespaces.present?
+ - if @own_namespace.present?
.fork-thumbnail-container.js-fork-content
%h5.gl-mt-0.gl-mb-0.gl-ml-3.gl-mr-3
= _("Select a namespace to fork the project")
- - @namespaces.each do |namespace|
- = render 'fork_button', namespace: namespace
- - else
- %strong
- = _("No available namespaces to fork the project.")
- %p.gl-mt-3
- = _("You must have permission to create a project in a namespace before forking.")
+ = render 'fork_button', namespace: @own_namespace
+ #fork-groups-mount-element{ data: { endpoint: new_project_fork_path(@project, format: :json), can_create_project: current_user.can_create_project?.to_s } }
diff --git a/changelogs/unreleased/227598-make-list-bullet-char-configurable.yml b/changelogs/unreleased/227598-make-list-bullet-char-configurable.yml
new file mode 100644
index 00000000000..4818df547b2
--- /dev/null
+++ b/changelogs/unreleased/227598-make-list-bullet-char-configurable.yml
@@ -0,0 +1,5 @@
+---
+title: Set default bullet char character as - when generating markdown in Static Site Editor
+merge_request: 36820
+author:
+type: other
diff --git a/changelogs/unreleased/229158-remove-pagerduty_webhook-feature-flag.yml b/changelogs/unreleased/229158-remove-pagerduty_webhook-feature-flag.yml
new file mode 100644
index 00000000000..0d00b486f43
--- /dev/null
+++ b/changelogs/unreleased/229158-remove-pagerduty_webhook-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Add PagerDuty incident integration.
+merge_request: 37193
+author:
+type: added
diff --git a/changelogs/unreleased/31176-wiki-page-size-validation.yml b/changelogs/unreleased/31176-wiki-page-size-validation.yml
new file mode 100644
index 00000000000..659252a5600
--- /dev/null
+++ b/changelogs/unreleased/31176-wiki-page-size-validation.yml
@@ -0,0 +1,5 @@
+---
+title: Add limit for wiki page content size
+merge_request: 36729
+author:
+type: performance
diff --git a/changelogs/unreleased/tags-controller-spec-debug.yml b/changelogs/unreleased/tags-controller-spec-debug.yml
new file mode 100644
index 00000000000..bae0da12078
--- /dev/null
+++ b/changelogs/unreleased/tags-controller-spec-debug.yml
@@ -0,0 +1,5 @@
+---
+title: Fix release evidence sometimes not being collected
+merge_request: 37184
+author:
+type: fixed
diff --git a/changelogs/unreleased/tchu-fix-explore-projects-controller-n-1.yml b/changelogs/unreleased/tchu-fix-explore-projects-controller-n-1.yml
new file mode 100644
index 00000000000..3386fdf1b29
--- /dev/null
+++ b/changelogs/unreleased/tchu-fix-explore-projects-controller-n-1.yml
@@ -0,0 +1,5 @@
+---
+title: Fix N+1 issue in Explore Projects controller.
+merge_request: 36874
+author:
+type: performance
diff --git a/changelogs/unreleased/xanf-improve-fork-page-design.yml b/changelogs/unreleased/xanf-improve-fork-page-design.yml
new file mode 100644
index 00000000000..eabda2de459
--- /dev/null
+++ b/changelogs/unreleased/xanf-improve-fork-page-design.yml
@@ -0,0 +1,5 @@
+---
+title: Improved fork page design
+merge_request: 35592
+author:
+type: changed
diff --git a/db/migrate/20200713141854_add_wiki_page_max_content_bytes_to_application_settings.rb b/db/migrate/20200713141854_add_wiki_page_max_content_bytes_to_application_settings.rb
new file mode 100644
index 00000000000..c0763d9816c
--- /dev/null
+++ b/db/migrate/20200713141854_add_wiki_page_max_content_bytes_to_application_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddWikiPageMaxContentBytesToApplicationSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :application_settings, :wiki_page_max_content_bytes, :bigint, default: 50.megabytes, null: false
+ end
+end
diff --git a/db/post_migrate/20200608203426_set_proper_lock_version_indices.rb b/db/post_migrate/20200608203426_set_proper_lock_version_indices.rb
index 489a158ea3a..924ca73e6cc 100644
--- a/db/post_migrate/20200608203426_set_proper_lock_version_indices.rb
+++ b/db/post_migrate/20200608203426_set_proper_lock_version_indices.rb
@@ -12,9 +12,9 @@ class SetProperLockVersionIndices < ActiveRecord::Migration[6.0]
remove_concurrent_index :merge_requests, :lock_version, where: "lock_version IS NULL"
remove_concurrent_index :issues, :lock_version, where: "lock_version IS NULL"
- add_concurrent_index :epics, :id, where: "lock_version IS NULL"
- add_concurrent_index :merge_requests, :id, where: "lock_version IS NULL"
- add_concurrent_index :issues, :id, where: "lock_version IS NULL"
+ add_concurrent_index :epics, :id, where: "lock_version IS NULL", name: 'index_epics_on_id'
+ add_concurrent_index :merge_requests, :id, where: "lock_version IS NULL", name: 'index_merge_requests_on_id'
+ add_concurrent_index :issues, :id, where: "lock_version IS NULL", name: 'index_issues_on_id'
end
def down
@@ -22,8 +22,8 @@ class SetProperLockVersionIndices < ActiveRecord::Migration[6.0]
add_concurrent_index :merge_requests, :lock_version, where: "lock_version IS NULL"
add_concurrent_index :issues, :lock_version, where: "lock_version IS NULL"
- remove_concurrent_index :epics, :id, where: "lock_version IS NULL"
- remove_concurrent_index :merge_requests, :id, where: "lock_version IS NULL"
- remove_concurrent_index :issues, :id, where: "lock_version IS NULL"
+ remove_concurrent_index_by_name :epics, name: 'index_epics_on_id'
+ remove_concurrent_index_by_name :merge_requests, name: 'index_merge_requests_on_id'
+ remove_concurrent_index_by_name :issues, name: 'index_issues_on_id'
end
end
diff --git a/db/post_migrate/20200608212030_lock_version_cleanup_for_epics.rb b/db/post_migrate/20200608212030_lock_version_cleanup_for_epics.rb
index 2c319be37a3..aafa6a83200 100644
--- a/db/post_migrate/20200608212030_lock_version_cleanup_for_epics.rb
+++ b/db/post_migrate/20200608212030_lock_version_cleanup_for_epics.rb
@@ -9,10 +9,10 @@ class LockVersionCleanupForEpics < ActiveRecord::Migration[6.0]
def up
validate_not_null_constraint :epics, :lock_version
- remove_concurrent_index :epics, :id, where: "lock_version IS NULL"
+ remove_concurrent_index_by_name :epics, name: 'index_epics_on_id'
end
def down
- add_concurrent_index :epics, :id, where: "lock_version IS NULL"
+ add_concurrent_index :epics, :id, where: "lock_version IS NULL", name: 'index_epics_on_id'
end
end
diff --git a/db/post_migrate/20200608212435_lock_version_cleanup_for_merge_requests.rb b/db/post_migrate/20200608212435_lock_version_cleanup_for_merge_requests.rb
index 2606016b8a9..cb8ab86b6a3 100644
--- a/db/post_migrate/20200608212435_lock_version_cleanup_for_merge_requests.rb
+++ b/db/post_migrate/20200608212435_lock_version_cleanup_for_merge_requests.rb
@@ -9,10 +9,10 @@ class LockVersionCleanupForMergeRequests < ActiveRecord::Migration[6.0]
def up
validate_not_null_constraint :merge_requests, :lock_version
- remove_concurrent_index :merge_requests, :id, where: "lock_version IS NULL"
+ remove_concurrent_index_by_name :merge_requests, name: 'index_merge_requests_on_id'
end
def down
- add_concurrent_index :merge_requests, :id, where: "lock_version IS NULL"
+ add_concurrent_index :merge_requests, :id, where: "lock_version IS NULL", name: 'index_merge_requests_on_id'
end
end
diff --git a/db/post_migrate/20200608212549_lock_version_cleanup_for_issues.rb b/db/post_migrate/20200608212549_lock_version_cleanup_for_issues.rb
index 54de3ac8000..ad3fea8b131 100644
--- a/db/post_migrate/20200608212549_lock_version_cleanup_for_issues.rb
+++ b/db/post_migrate/20200608212549_lock_version_cleanup_for_issues.rb
@@ -9,10 +9,10 @@ class LockVersionCleanupForIssues < ActiveRecord::Migration[6.0]
def up
validate_not_null_constraint :issues, :lock_version
- remove_concurrent_index :issues, :id, where: "lock_version IS NULL"
+ remove_concurrent_index_by_name :issues, name: 'index_issues_on_id'
end
def down
- add_concurrent_index :issues, :id, where: "lock_version IS NULL"
+ add_concurrent_index :issues, :id, where: "lock_version IS NULL", name: 'index_issues_on_id'
end
end
diff --git a/db/structure.sql b/db/structure.sql
index 4cf825da8c9..96d3dd5bbc1 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -9172,6 +9172,7 @@ CREATE TABLE public.application_settings (
group_download_export_limit integer DEFAULT 1 NOT NULL,
maintenance_mode boolean DEFAULT false NOT NULL,
maintenance_mode_message text,
+ wiki_page_max_content_bytes bigint DEFAULT 52428800 NOT NULL,
CONSTRAINT check_51700b31b5 CHECK ((char_length(default_branch_name) <= 255)),
CONSTRAINT check_9c6c447a13 CHECK ((char_length(maintenance_mode_message) <= 255)),
CONSTRAINT check_d03919528d CHECK ((char_length(container_registry_vendor) <= 255)),
@@ -23861,6 +23862,7 @@ COPY "schema_migrations" (version) FROM STDIN;
20200712084655
20200712235622
20200713071042
+20200713141854
20200713152443
20200716044023
20200716120419
diff --git a/doc/administration/high_availability/gitlab.md b/doc/administration/high_availability/gitlab.md
index dc8c997bab5..6229eb36742 100644
--- a/doc/administration/high_availability/gitlab.md
+++ b/doc/administration/high_availability/gitlab.md
@@ -170,7 +170,7 @@ If you enable Monitoring, it must be enabled on **all** GitLab servers.
sidekiq['listen_address'] = "0.0.0.0"
puma['listen'] = '0.0.0.0'
- # Add the monitoring node's IP address to the monitoring whitelist and allow it to
+ # Add the monitoring node's IP address to the monitoring list that allows it to
# scrape the NGINX metrics. Replace placeholder `monitoring.gitlab.example.com` with
# the address and/or subnets gathered from the monitoring node(s).
gitlab_rails['monitoring_whitelist'] = ['monitoring.gitlab.example.com', '127.0.0.0/8']
diff --git a/doc/administration/high_availability/sidekiq.md b/doc/administration/high_availability/sidekiq.md
index 98a9af64e5e..21664c084a6 100644
--- a/doc/administration/high_availability/sidekiq.md
+++ b/doc/administration/high_availability/sidekiq.md
@@ -66,7 +66,7 @@ you want using steps 1 and 2 from the GitLab downloads page.
gitlab_rails['auto_migrate'] = false
```
- Remember to add the Sidekiq nodes to the PostgreSQL whitelist:
+ Remember to add the Sidekiq nodes to PostgreSQL's trusted addresses:
```ruby
postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.10.1.30/32 10.10.1.31/32 10.10.1.32/32 10.10.1.33/32 10.10.1.38/32)
diff --git a/doc/administration/index.md b/doc/administration/index.md
index fa415e5f78d..1978ce62db3 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -163,7 +163,11 @@ Learn how to install, configure, update, and maintain your GitLab instance.
## Snippet settings
-- [Setting snippet content size limit](snippets/index.md): Set a maximum size limit for snippets' content.
+- [Setting snippet content size limit](snippets/index.md): Set a maximum content size limit for snippets.
+
+## Wiki settings
+
+- [Setting wiki page content size limit](wikis/index.md): Set a maximum content size limit for wiki pages.
## Git configuration options
diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md
index 6d2fbd95d5e..b8915f8a4a3 100644
--- a/doc/administration/instance_limits.md
+++ b/doc/administration/instance_limits.md
@@ -408,6 +408,7 @@ Set the limit to `0` to disable it.
## Wiki limits
+- [Wiki page content size limit](wikis/index.md#wiki-page-content-size-limit).
- [Length restrictions for file and directory names](../user/project/wiki/index.md#length-restrictions-for-file-and-directory-names).
## Snippets limits
diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md
index fbb9c32442a..0b4114bca6e 100644
--- a/doc/administration/reference_architectures/5k_users.md
+++ b/doc/administration/reference_architectures/5k_users.md
@@ -1,73 +1,1767 @@
+---
+reading_time: true
+---
+
# Reference architecture: up to 5,000 users
This page describes GitLab reference architecture for up to 5,000 users.
For a full list of reference architectures, see
[Available reference architectures](index.md#available-reference-architectures).
+NOTE: **Note:**
+The 5,000-user reference architecture documented below is
+designed to help your organization achieve a highly-available GitLab deployment.
+If you do not have the expertise or need to maintain a highly-available
+environment, you can have a simpler and less costly-to-operate environment by
+following the [2,000-user reference architecture](2k_users.md).
+
> - **Supported users (approximate):** 5,000
> - **High Availability:** True
> - **Test RPS rates:** API: 100 RPS, Web: 10 RPS, Git: 10 RPS
-| Service | Nodes | Configuration ([8](#footnotes)) | GCP | AWS | Azure |
-|--------------------------------------------------------------|-------|---------------------------------|---------------|-----------------------|----------------|
-| GitLab Rails ([1](#footnotes)) | 3 | 16 vCPU, 14.4GB Memory | `n1-highcpu-16` | `c5.4xlarge` | F16s v2 |
-| PostgreSQL | 3 | 2 vCPU, 7.5GB Memory | `n1-standard-2` | `m5.large` | D2s v3 |
-| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | F2s v2 |
-| Gitaly ([2](#footnotes)) ([5](#footnotes)) ([7](#footnotes)) | X | 8 vCPU, 30GB Memory | `n1-standard-8` | `m5.2xlarge` | D8s v3 |
-| Redis ([3](#footnotes)) | 3 | 2 vCPU, 7.5GB Memory | `n1-standard-2` | `m5.large` | D2s v3 |
-| Consul + Sentinel ([3](#footnotes)) | 3 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | F2s v2 |
-| Sidekiq | 4 | 2 vCPU, 7.5GB Memory | `n1-standard-2` | `m5.large` | D2s v3 |
-| Object Storage ([4](#footnotes)) | - | - | - | - | - |
-| NFS Server ([5](#footnotes)) ([7](#footnotes)) | 1 | 4 vCPU, 3.6GB Memory | `n1-highcpu-4` | `c5.xlarge` | F4s v2 |
-| Monitoring node | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | F2s v2 |
-| External load balancing node ([6](#footnotes)) | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | F2s v2 |
-| Internal load balancing node ([6](#footnotes)) | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | F2s v2 |
-
-## Footnotes
-
-1. In our architectures we run each GitLab Rails node using the Puma webserver
- and have its number of workers set to 90% of available CPUs along with four threads. For
- nodes that are running Rails with other components the worker value should be reduced
- accordingly where we've found 50% achieves a good balance but this is dependent
- on workload.
-
-1. Gitaly node requirements are dependent on customer data, specifically the number of
- projects and their sizes. We recommend two nodes as an absolute minimum for HA environments
- and at least four nodes should be used when supporting 50,000 or more users.
- We also recommend that each Gitaly node should store no more than 5TB of data
- and have the number of [`gitaly-ruby` workers](../gitaly/index.md#gitaly-ruby)
- set to 20% of available CPUs. Additional nodes should be considered in conjunction
- with a review of expected data size and spread based on the recommendations above.
-
-1. Recommended Redis setup differs depending on the size of the architecture.
- For smaller architectures (less than 3,000 users) a single instance should suffice.
- For medium sized installs (3,000 - 5,000) we suggest one Redis cluster for all
- classes and that Redis Sentinel is hosted alongside Consul.
- For larger architectures (10,000 users or more) we suggest running a separate
- [Redis Cluster](../redis/replication_and_failover.md#running-multiple-redis-clusters) for the Cache class
- and another for the Queues and Shared State classes respectively. We also recommend
- that you run the Redis Sentinel clusters separately for each Redis Cluster.
-
-1. For data objects such as LFS, Uploads, Artifacts, etc. We recommend an [Object Storage service](../object_storage.md)
- over NFS where possible, due to better performance and availability.
-
-1. NFS can be used as an alternative for both repository data (replacing Gitaly) and
- object storage but this isn't typically recommended for performance reasons. Note however it is required for
- [GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196).
-
-1. Our architectures have been tested and validated with [HAProxy](https://www.haproxy.org/)
- as the load balancer. Although other load balancers with similar feature sets
- could also be used, those load balancers have not been validated.
-
-1. We strongly recommend that any Gitaly or NFS nodes be set up with SSD disks over
- HDD with a throughput of at least 8,000 IOPS for read operations and 2,000 IOPS for write
- as these components have heavy I/O. These IOPS values are recommended only as a starter
- as with time they may be adjusted higher or lower depending on the scale of your
- environment's workload. If you're running the environment on a Cloud provider
- you may need to refer to their documentation on how configure IOPS correctly.
-
-1. The architectures were built and tested with the [Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
- CPU platform on GCP. On different hardware you may find that adjustments, either lower
- or higher, are required for your CPU or Node counts accordingly. For more information, a
- [Sysbench](https://github.com/akopytov/sysbench) benchmark of the CPU can be found
- [here](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks).
+| Service | Nodes | Configuration | GCP | AWS | Azure |
+|--------------------------------------------------------------|-------|---------------------------------|-----------------|-----------------------|----------------|
+| External load balancing node | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Redis | 3 | 2 vCPU, 7.5GB Memory | `n1-standard-2` | `m5.large` | `D2s v3` |
+| Consul + Sentinel | 3 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| PostgreSQL | 3 | 2 vCPU, 7.5GB Memory | `n1-standard-2` | `m5.large` | `D2s v3` |
+| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Internal load balancing node | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Gitaly | 2 minimum | 8 vCPU, 30GB Memory | `n1-standard-8` | `m5.2xlarge` | `D8s v3` |
+| Sidekiq | 4 | 2 vCPU, 7.5GB Memory | `n1-standard-2` | `m5.large` | `D2s v3` |
+| GitLab Rails | 3 | 16 vCPU, 14.4GB Memory | `n1-highcpu-16` | `c5.4xlarge` | `F16s v2` |
+| Monitoring node | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Object Storage | n/a | n/a | n/a | n/a | n/a |
+| NFS Server (optional, not recommended) | 1 | 4 vCPU, 3.6GB Memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+
+The architectures were built and tested with the [Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
+CPU platform on GCP. On different hardware you may find that adjustments, either lower
+or higher, are required for your CPU or Node counts accordingly. For more information, a
+[Sysbench](https://github.com/akopytov/sysbench) benchmark of the CPU can be found
+[here](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks).
+
+For data objects such as LFS, Uploads, Artifacts, etc, an [object storage service](#configure-the-object-storage)
+is recommended over NFS where possible, due to better performance and availability.
+Since this doesn't require a node to be set up, it's marked as not applicable (n/a)
+in the table above.
+
+## Setup components
+
+To set up GitLab and its components to accommodate up to 5,000 users:
+
+1. [Configure the external load balancing node](#configure-the-external-load-balancer)
+ that will handle the load balancing of the two GitLab application services nodes.
+1. [Configure Redis](#configure-redis).
+1. [Configure Consul and Sentinel](#configure-consul-and-sentinel).
+1. [Configure PostgreSQL](#configure-postgresql), the database for GitLab.
+1. [Configure PgBouncer](#configure-pgbouncer).
+1. [Configure the internal load balancing node](#configure-the-internal-load-balancer)
+1. [Configure Gitaly](#configure-gitaly),
+ which provides access to the Git repositories.
+1. [Configure Sidekiq](#configure-sidekiq).
+1. [Configure the main GitLab Rails application](#configure-gitlab-rails)
+ to run Puma/Unicorn, Workhorse, GitLab Shell, and to serve all frontend requests (UI, API, Git
+ over HTTP/SSH).
+1. [Configure Prometheus](#configure-prometheus) to monitor your GitLab environment.
+1. [Configure the Object Storage](#configure-the-object-storage)
+ used for shared data objects.
+1. [Configure NFS (Optional)](#configure-nfs-optional)
+ to have shared disk storage service as an alternative to Gitaly and/or Object Storage (although
+ not recommended). NFS is required for GitLab Pages, you can skip this step if you're not using
+ that feature.
+
+We start with all servers on the same 10.6.0.0/16 private network range, they
+can connect to each other freely on those addresses.
+
+Here is a list and description of each machine and the assigned IP:
+
+- `10.6.0.10`: External Load Balancer
+- `10.6.0.61`: Redis Primary
+- `10.6.0.62`: Redis Replica 1
+- `10.6.0.63`: Redis Replica 2
+- `10.6.0.11`: Consul/Sentinel 1
+- `10.6.0.12`: Consul/Sentinel 2
+- `10.6.0.13`: Consul/Sentinel 3
+- `10.6.0.31`: PostgreSQL primary
+- `10.6.0.32`: PostgreSQL secondary 1
+- `10.6.0.33`: PostgreSQL secondary 2
+- `10.6.0.21`: PgBouncer 1
+- `10.6.0.22`: PgBouncer 2
+- `10.6.0.23`: PgBouncer 3
+- `10.6.0.20`: Internal Load Balancer
+- `10.6.0.51`: Gitaly 1
+- `10.6.0.52`: Gitaly 2
+- `10.6.0.71`: Sidekiq 1
+- `10.6.0.72`: Sidekiq 2
+- `10.6.0.73`: Sidekiq 3
+- `10.6.0.74`: Sidekiq 4
+- `10.6.0.41`: GitLab application 1
+- `10.6.0.42`: GitLab application 2
+- `10.6.0.43`: GitLab application 3
+- `10.6.0.81`: Prometheus
+
+## Configure the external load balancer
+
+NOTE: **Note:**
+This architecture has been tested and validated with [HAProxy](https://www.haproxy.org/)
+as the load balancer. Although other load balancers with similar feature sets
+could also be used, those load balancers have not been validated.
+
+In an active/active GitLab configuration, you will need a load balancer to route
+traffic to the application servers. The specifics on which load balancer to use
+or the exact configuration is beyond the scope of GitLab documentation. We hope
+that if you're managing multi-node systems like GitLab you have a load balancer of
+choice already. Some examples including HAProxy (open-source), F5 Big-IP LTM,
+and Citrix Net Scaler. This documentation will outline what ports and protocols
+you need to use with GitLab.
+
+The next question is how you will handle SSL in your environment.
+There are several different options:
+
+- [The application node terminates SSL](#application-node-terminates-ssl).
+- [The load balancer terminates SSL without backend SSL](#load-balancer-terminates-ssl-without-backend-ssl)
+ and communication is not secure between the load balancer and the application node.
+- [The load balancer terminates SSL with backend SSL](#load-balancer-terminates-ssl-with-backend-ssl)
+ and communication is *secure* between the load balancer and the application node.
+
+### Application node terminates SSL
+
+Configure your load balancer to pass connections on port 443 as `TCP` rather
+than `HTTP(S)` protocol. This will pass the connection to the application node's
+NGINX service untouched. NGINX will have the SSL certificate and listen on port 443.
+
+See the [NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
+for details on managing SSL certificates and configuring NGINX.
+
+### Load balancer terminates SSL without backend SSL
+
+Configure your load balancer to use the `HTTP(S)` protocol rather than `TCP`.
+The load balancer will then be responsible for managing SSL certificates and
+terminating SSL.
+
+Since communication between the load balancer and GitLab will not be secure,
+there is some additional configuration needed. See the
+[NGINX proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#supporting-proxied-ssl)
+for details.
+
+### Load balancer terminates SSL with backend SSL
+
+Configure your load balancer(s) to use the 'HTTP(S)' protocol rather than 'TCP'.
+The load balancer(s) will be responsible for managing SSL certificates that
+end users will see.
+
+Traffic will also be secure between the load balancer(s) and NGINX in this
+scenario. There is no need to add configuration for proxied SSL since the
+connection will be secure all the way. However, configuration will need to be
+added to GitLab to configure SSL certificates. See
+[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
+for details on managing SSL certificates and configuring NGINX.
+
+### Ports
+
+The basic ports to be used are shown in the table below.
+
+| LB Port | Backend Port | Protocol |
+| ------- | ------------ | ------------------------ |
+| 80 | 80 | HTTP (*1*) |
+| 443 | 443 | TCP or HTTPS (*1*) (*2*) |
+| 22 | 22 | TCP |
+
+- (*1*): [Web terminal](../../ci/environments/index.md#web-terminals) support requires
+ your load balancer to correctly handle WebSocket connections. When using
+ HTTP or HTTPS proxying, this means your load balancer must be configured
+ to pass through the `Connection` and `Upgrade` hop-by-hop headers. See the
+ [web terminal](../integration/terminal.md) integration guide for
+ more details.
+- (*2*): When using HTTPS protocol for port 443, you will need to add an SSL
+ certificate to the load balancers. If you wish to terminate SSL at the
+ GitLab application server instead, use TCP protocol.
+
+If you're using GitLab Pages with custom domain support you will need some
+additional port configurations.
+GitLab Pages requires a separate virtual IP address. Configure DNS to point the
+`pages_external_url` from `/etc/gitlab/gitlab.rb` at the new virtual IP address. See the
+[GitLab Pages documentation](../pages/index.md) for more information.
+
+| LB Port | Backend Port | Protocol |
+| ------- | ------------- | --------- |
+| 80 | Varies (*1*) | HTTP |
+| 443 | Varies (*1*) | TCP (*2*) |
+
+- (*1*): The backend port for GitLab Pages depends on the
+ `gitlab_pages['external_http']` and `gitlab_pages['external_https']`
+ setting. See [GitLab Pages documentation](../pages/index.md) for more details.
+- (*2*): Port 443 for GitLab Pages should always use the TCP protocol. Users can
+ configure custom domains with custom SSL, which would not be possible
+ if SSL was terminated at the load balancer.
+
+#### Alternate SSH Port
+
+Some organizations have policies against opening SSH port 22. In this case,
+it may be helpful to configure an alternate SSH hostname that allows users
+to use SSH on port 443. An alternate SSH hostname will require a new virtual IP address
+compared to the other GitLab HTTP configuration above.
+
+Configure DNS for an alternate SSH hostname such as `altssh.gitlab.example.com`.
+
+| LB Port | Backend Port | Protocol |
+| ------- | ------------ | -------- |
+| 443 | 22 | TCP |
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#setup-components">
+ Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+## Configure Redis
+
+Using [Redis](https://redis.io/) in scalable environment is possible using a **Primary** x **Replica**
+topology with a [Redis Sentinel](https://redis.io/topics/sentinel) service to watch and automatically
+start the failover procedure.
+
+Redis requires authentication if used with Sentinel. See
+[Redis Security](https://redis.io/topics/security) documentation for more
+information. We recommend using a combination of a Redis password and tight
+firewall rules to secure your Redis service.
+You are highly encouraged to read the [Redis Sentinel](https://redis.io/topics/sentinel) documentation
+before configuring Redis with GitLab to fully understand the topology and
+architecture.
+
+In this section, you'll be guided through configuring an external Redis instance
+to be used with GitLab. The following IPs will be used as an example:
+
+- `10.6.0.61`: Redis Primary
+- `10.6.0.62`: Redis Replica 1
+- `10.6.0.63`: Redis Replica 2
+
+### Provide your own Redis instance
+
+Managed Redis from cloud providers such as AWS ElastiCache will work. If these
+services support high availability, be sure it is **not** the Redis Cluster type.
+
+Redis version 5.0 or higher is required, as this is what ships with
+Omnibus GitLab packages starting with GitLab 13.0. Older Redis versions
+do not support an optional count argument to SPOP which is now required for
+[Merge Trains](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md).
+
+Note the Redis node's IP address or hostname, port, and password (if required).
+These will be necessary when configuring the
+[GitLab application servers](#configure-gitlab-rails) later.
+
+### Standalone Redis using Omnibus GitLab
+
+This is the section where we install and set up the new Redis instances.
+
+The requirements for a Redis setup are the following:
+
+1. All Redis nodes must be able to talk to each other and accept incoming
+ connections over Redis (`6379`) and Sentinel (`26379`) ports (unless you
+ change the default ones).
+1. The server that hosts the GitLab application must be able to access the
+ Redis nodes.
+1. Protect the nodes from access from external networks
+ ([Internet](https://gitlab.com/gitlab-org/gitlab-foss/uploads/c4cc8cd353604bd80315f9384035ff9e/The_Internet_IT_Crowd.png)),
+ using a firewall.
+
+NOTE: **Note:**
+Redis nodes (both primary and replica) will need the same password defined in
+`redis['password']`. At any time during a failover the Sentinels can
+reconfigure a node and change its status from primary to replica and vice versa.
+
+#### Configuring the primary Redis instance
+
+1. SSH into the **Primary** Redis server.
+1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab
+ package you want using **steps 1 and 2** from the GitLab downloads page.
+ - Make sure you select the correct Omnibus package, with the same version
+ and type (Community, Enterprise editions) of your current install.
+ - Do not complete any other steps on the download page.
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
+
+ ```ruby
+ # Specify server role as 'redis_master_role'
+ roles ['redis_master_role']
+
+ # IP address pointing to a local IP that the other machines can reach to.
+ # You can also set bind to '0.0.0.0' which listen in all interfaces.
+ # If you really need to bind to an external accessible IP, make
+ # sure you add extra firewall rules to prevent unauthorized access.
+ redis['bind'] = '10.6.0.61'
+
+ # Define a port so Redis can listen for TCP requests which will allow other
+ # machines to connect to it.
+ redis['port'] = 6379
+
+ # Set up password authentication for Redis (use the same password in all nodes).
+ redis['password'] = 'redis-password-goes-here'
+
+ ## Enable service discovery for Prometheus
+ consul['enable'] = true
+ consul['monitoring_service_discovery'] = true
+
+ ## The IPs of the Consul server nodes
+ ## You can also use FQDNs and intermix them with IPs
+ consul['configuration'] = {
+ retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13),
+ }
+
+ # Set the network addresses that the exporters will listen on
+ node_exporter['listen_address'] = '0.0.0.0:9100'
+ redis_exporter['listen_address'] = '0.0.0.0:9121'
+ redis_exporter['flags'] = {
+ 'redis.addr' => 'redis://10.6.0.61:6379',
+ 'redis.password' => 'redis-password-goes-here',
+ }
+
+ # Disable auto migrations
+ gitlab_rails['auto_migrate'] = false
+ ```
+
+1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
+NOTE: **Note:**
+You can specify multiple roles like sentinel and Redis as:
+`roles ['redis_sentinel_role', 'redis_master_role']`.
+Read more about [roles](https://docs.gitlab.com/omnibus/roles/).
+
+You can list the current Redis Primary, Replica status via:
+
+```shell
+/opt/gitlab/embedded/bin/redis-cli -h <host> -a 'redis-password-goes-here' info replication
+```
+
+Show running GitLab services via:
+
+```shell
+gitlab-ctl status
+```
+
+The output should be similar to the following:
+
+```plaintext
+run: consul: (pid 30043) 76863s; run: log: (pid 29691) 76892s
+run: logrotate: (pid 31152) 3070s; run: log: (pid 29595) 76908s
+run: node-exporter: (pid 30064) 76862s; run: log: (pid 29624) 76904s
+run: redis: (pid 30070) 76861s; run: log: (pid 29573) 76914s
+run: redis-exporter: (pid 30075) 76861s; run: log: (pid 29674) 76896s
+```
+
+#### Configuring the replica Redis instances
+
+1. SSH into the **replica** Redis server.
+1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab
+ package you want using **steps 1 and 2** from the GitLab downloads page.
+ - Make sure you select the correct Omnibus package, with the same version
+ and type (Community, Enterprise editions) of your current install.
+ - Do not complete any other steps on the download page.
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
+
+ ```ruby
+ # Specify server role as 'redis_replica_role'
+ roles ['redis_replica_role']
+
+ # IP address pointing to a local IP that the other machines can reach to.
+ # You can also set bind to '0.0.0.0' which listen in all interfaces.
+ # If you really need to bind to an external accessible IP, make
+ # sure you add extra firewall rules to prevent unauthorized access.
+ redis['bind'] = '10.6.0.62'
+
+ # Define a port so Redis can listen for TCP requests which will allow other
+ # machines to connect to it.
+ redis['port'] = 6379
+
+ # The same password for Redis authentication you set up for the primary node.
+ redis['password'] = 'redis-password-goes-here'
+
+ # The IP of the primary Redis node.
+ redis['master_ip'] = '10.6.0.61'
+
+ # Port of primary Redis server, uncomment to change to non default. Defaults
+ # to `6379`.
+ #redis['master_port'] = 6379
+
+ ## Enable service discovery for Prometheus
+ consul['enable'] = true
+ consul['monitoring_service_discovery'] = true
+
+ ## The IPs of the Consul server nodes
+ ## You can also use FQDNs and intermix them with IPs
+ consul['configuration'] = {
+ retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13),
+ }
+
+ # Set the network addresses that the exporters will listen on
+ node_exporter['listen_address'] = '0.0.0.0:9100'
+ redis_exporter['listen_address'] = '0.0.0.0:9121'
+ redis_exporter['flags'] = {
+ 'redis.addr' => 'redis://10.6.0.62:6379',
+ 'redis.password' => 'redis-password-goes-here',
+ }
+
+ # Disable auto migrations
+ gitlab_rails['auto_migrate'] = false
+ ```
+
+1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+1. Go through the steps again for all the other replica nodes, and
+ make sure to set up the IPs correctly.
+
+NOTE: **Note:**
+You can specify multiple roles like sentinel and Redis as:
+`roles ['redis_sentinel_role', 'redis_master_role']`.
+Read more about [roles](https://docs.gitlab.com/omnibus/roles/).
+
+These values don't have to be changed again in `/etc/gitlab/gitlab.rb` after
+a failover, as the nodes will be managed by the [Sentinels](#configure-consul-and-sentinel), and even after a
+`gitlab-ctl reconfigure`, they will get their configuration restored by
+the same Sentinels.
+
+Advanced [configuration options](https://docs.gitlab.com/omnibus/settings/redis.html)
+are supported and can be added if needed.
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#setup-components">
+ Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+## Configure Consul and Sentinel
+
+NOTE: **Note:**
+If you are using an external Redis Sentinel instance, be sure
+to exclude the `requirepass` parameter from the Sentinel
+configuration. This parameter will cause clients to report `NOAUTH
+Authentication required.`. [Redis Sentinel 3.2.x does not support
+password authentication](https://github.com/antirez/redis/issues/3279).
+
+Now that the Redis servers are all set up, let's configure the Sentinel
+servers. The following IPs will be used as an example:
+
+- `10.6.0.11`: Consul/Sentinel 1
+- `10.6.0.12`: Consul/Sentinel 2
+- `10.6.0.13`: Consul/Sentinel 3
+
+To configure the Sentinel:
+
+1. SSH into the server that will host Consul/Sentinel.
+1. [Download/install](https://about.gitlab.com/install/) the
+ Omnibus GitLab Enterprise Edition package using **steps 1 and 2** from the
+ GitLab downloads page.
+ - Make sure you select the correct Omnibus package, with the same version
+ the GitLab application is running.
+ - Do not complete any other steps on the download page.
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
+
+ ```ruby
+ roles ['redis_sentinel_role', 'consul_role']
+
+ # Must be the same in every sentinel node
+ redis['master_name'] = 'gitlab-redis'
+
+ # The same password for Redis authentication you set up for the primary node.
+ redis['master_password'] = 'redis-password-goes-here'
+
+ # The IP of the primary Redis node.
+ redis['master_ip'] = '10.6.0.61'
+
+ # Define a port so Redis can listen for TCP requests which will allow other
+ # machines to connect to it.
+ redis['port'] = 6379
+
+ # Port of primary Redis server, uncomment to change to non default. Defaults
+ # to `6379`.
+ #redis['master_port'] = 6379
+
+ ## Configure Sentinel
+ sentinel['bind'] = '10.6.0.11'
+
+ # Port that Sentinel listens on, uncomment to change to non default. Defaults
+ # to `26379`.
+ # sentinel['port'] = 26379
+
+ ## Quorum must reflect the amount of voting sentinels it take to start a failover.
+ ## Value must NOT be greater then the amount of sentinels.
+ ##
+ ## The quorum can be used to tune Sentinel in two ways:
+ ## 1. If a the quorum is set to a value smaller than the majority of Sentinels
+ ## we deploy, we are basically making Sentinel more sensible to primary failures,
+ ## triggering a failover as soon as even just a minority of Sentinels is no longer
+ ## able to talk with the primary.
+ ## 1. If a quorum is set to a value greater than the majority of Sentinels, we are
+ ## making Sentinel able to failover only when there are a very large number (larger
+ ## than majority) of well connected Sentinels which agree about the primary being down.s
+ sentinel['quorum'] = 2
+
+ ## Consider unresponsive server down after x amount of ms.
+ # sentinel['down_after_milliseconds'] = 10000
+
+ ## Specifies the failover timeout in milliseconds. It is used in many ways:
+ ##
+ ## - The time needed to re-start a failover after a previous failover was
+ ## already tried against the same primary by a given Sentinel, is two
+ ## times the failover timeout.
+ ##
+ ## - The time needed for a replica replicating to a wrong primary according
+ ## to a Sentinel current configuration, to be forced to replicate
+ ## with the right primary, is exactly the failover timeout (counting since
+ ## the moment a Sentinel detected the misconfiguration).
+ ##
+ ## - The time needed to cancel a failover that is already in progress but
+ ## did not produced any configuration change (REPLICAOF NO ONE yet not
+ ## acknowledged by the promoted replica).
+ ##
+ ## - The maximum time a failover in progress waits for all the replica to be
+ ## reconfigured as replicas of the new primary. However even after this time
+ ## the replicas will be reconfigured by the Sentinels anyway, but not with
+ ## the exact parallel-syncs progression as specified.
+ # sentinel['failover_timeout'] = 60000
+
+ ## Enable service discovery for Prometheus
+ consul['enable'] = true
+ consul['monitoring_service_discovery'] = true
+
+ ## The IPs of the Consul server nodes
+ ## You can also use FQDNs and intermix them with IPs
+ consul['configuration'] = {
+ server: true,
+ retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13),
+ }
+
+ # Set the network addresses that the exporters will listen on
+ node_exporter['listen_address'] = '0.0.0.0:9100'
+ redis_exporter['listen_address'] = '0.0.0.0:9121'
+
+ # Disable auto migrations
+ gitlab_rails['auto_migrate'] = false
+ ```
+
+1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+1. Go through the steps again for all the other Consul/Sentinel nodes, and
+ make sure you set up the correct IPs.
+
+NOTE: **Note:**
+A Consul leader will be elected when the provisioning of the third Consul server is completed.
+Viewing the Consul logs `sudo gitlab-ctl tail consul` will display
+`...[INFO] consul: New leader elected: ...`
+
+You can list the current Consul members (server, client):
+
+```shell
+sudo /opt/gitlab/embedded/bin/consul members
+```
+
+You can verify the GitLab services are running:
+
+```shell
+sudo gitlab-ctl status
+```
+
+The output should be similar to the following:
+
+```plaintext
+run: consul: (pid 30074) 76834s; run: log: (pid 29740) 76844s
+run: logrotate: (pid 30925) 3041s; run: log: (pid 29649) 76861s
+run: node-exporter: (pid 30093) 76833s; run: log: (pid 29663) 76855s
+run: sentinel: (pid 30098) 76832s; run: log: (pid 29704) 76850s
+```
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#setup-components">
+ Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+## Configure PostgreSQL
+
+In this section, you'll be guided through configuring an external PostgreSQL database
+to be used with GitLab.
+
+### Provide your own PostgreSQL instance
+
+If you're hosting GitLab on a cloud provider, you can optionally use a
+managed service for PostgreSQL. For example, AWS offers a managed Relational
+Database Service (RDS) that runs PostgreSQL.
+
+If you use a cloud-managed service, or provide your own PostgreSQL:
+
+1. Set up PostgreSQL according to the
+ [database requirements document](../../install/requirements.md#database).
+1. Set up a `gitlab` username with a password of your choice. The `gitlab` user
+ needs privileges to create the `gitlabhq_production` database.
+1. Configure the GitLab application servers with the appropriate details.
+ This step is covered in [Configuring the GitLab Rails application](#configure-gitlab-rails).
+
+### Standalone PostgreSQL using Omnibus GitLab
+
+The following IPs will be used as an example:
+
+- `10.6.0.31`: PostgreSQL primary
+- `10.6.0.32`: PostgreSQL secondary 1
+- `10.6.0.33`: PostgreSQL secondary 2
+
+First, make sure to [install](https://about.gitlab.com/install/)
+the Linux GitLab package **on each node**. Following the steps,
+install the necessary dependencies from step 1, and add the
+GitLab package repository from step 2. When installing GitLab
+in the second step, do not supply the `EXTERNAL_URL` value.
+
+#### PostgreSQL primary node
+
+1. SSH into the PostgreSQL primary node.
+1. Generate a password hash for the PostgreSQL username/password pair. This assumes you will use the default
+ username of `gitlab` (recommended). The command will request a password
+ and confirmation. Use the value that is output by this command in the next
+ step as the value of `<postgresql_password_hash>`:
+
+ ```shell
+ sudo gitlab-ctl pg-password-md5 gitlab
+ ```
+
+1. Generate a password hash for the PgBouncer username/password pair. This assumes you will use the default
+ username of `pgbouncer` (recommended). The command will request a password
+ and confirmation. Use the value that is output by this command in the next
+ step as the value of `<pgbouncer_password_hash>`:
+
+ ```shell
+ sudo gitlab-ctl pg-password-md5 pgbouncer
+ ```
+
+1. Generate a password hash for the Consul database username/password pair. This assumes you will use the default
+ username of `gitlab-consul` (recommended). The command will request a password
+ and confirmation. Use the value that is output by this command in the next
+ step as the value of `<consul_password_hash>`:
+
+ ```shell
+ sudo gitlab-ctl pg-password-md5 gitlab-consul
+ ```
+
+1. On the primary database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
+
+ ```ruby
+ # Disable all components except PostgreSQL and Repmgr and Consul
+ roles ['postgres_role']
+
+ # PostgreSQL configuration
+ postgresql['listen_address'] = '0.0.0.0'
+ postgresql['hot_standby'] = 'on'
+ postgresql['wal_level'] = 'replica'
+ postgresql['shared_preload_libraries'] = 'repmgr_funcs'
+
+ # Disable automatic database migrations
+ gitlab_rails['auto_migrate'] = false
+
+ # Configure the Consul agent
+ consul['services'] = %w(postgresql)
+
+ # START user configuration
+ # Please set the real values as explained in Required Information section
+ #
+ # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
+ postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>'
+ # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
+ postgresql['sql_user_password'] = '<postgresql_password_hash>'
+ # Set `max_wal_senders` to one more than the number of database nodes in the cluster.
+ # This is used to prevent replication from using up all of the
+ # available database connections.
+ postgresql['max_wal_senders'] = 4
+ postgresql['max_replication_slots'] = 4
+
+ # Replace XXX.XXX.XXX.XXX/YY with Network Address
+ postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24)
+ repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24)
+
+ ## Enable service discovery for Prometheus
+ consul['enable'] = true
+ consul['monitoring_service_discovery'] = true
+
+ # Set the network addresses that the exporters will listen on for monitoring
+ node_exporter['listen_address'] = '0.0.0.0:9100'
+ postgres_exporter['listen_address'] = '0.0.0.0:9187'
+ postgres_exporter['dbname'] = 'gitlabhq_production'
+ postgres_exporter['password'] = '<postgresql_password_hash>'
+
+ ## The IPs of the Consul server nodes
+ ## You can also use FQDNs and intermix them with IPs
+ consul['configuration'] = {
+ retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13),
+ }
+ #
+ # END user configuration
+ ```
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+1. You can list the current PostgreSQL primary, secondary nodes status via:
+
+ ```shell
+ sudo /opt/gitlab/bin/gitlab-ctl repmgr cluster show
+ ```
+
+1. Verify the GitLab services are running:
+
+ ```shell
+ sudo gitlab-ctl status
+ ```
+
+ The output should be similar to the following:
+
+ ```plaintext
+ run: consul: (pid 30593) 77133s; run: log: (pid 29912) 77156s
+ run: logrotate: (pid 23449) 3341s; run: log: (pid 29794) 77175s
+ run: node-exporter: (pid 30613) 77133s; run: log: (pid 29824) 77170s
+ run: postgres-exporter: (pid 30620) 77132s; run: log: (pid 29894) 77163s
+ run: postgresql: (pid 30630) 77132s; run: log: (pid 29618) 77181s
+ run: repmgrd: (pid 30639) 77132s; run: log: (pid 29985) 77150s
+ ```
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#setup-components">
+ Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+#### PostgreSQL secondary nodes
+
+1. On both the secondary nodes, add the same configuration specified above for the primary node
+ with an additional setting that will inform `gitlab-ctl` that they are standby nodes initially
+ and there's no need to attempt to register them as a primary node:
+
+ ```ruby
+ # Disable all components except PostgreSQL and Repmgr and Consul
+ roles ['postgres_role']
+
+ # PostgreSQL configuration
+ postgresql['listen_address'] = '0.0.0.0'
+ postgresql['hot_standby'] = 'on'
+ postgresql['wal_level'] = 'replica'
+ postgresql['shared_preload_libraries'] = 'repmgr_funcs'
+
+ # Disable automatic database migrations
+ gitlab_rails['auto_migrate'] = false
+
+ # Configure the Consul agent
+ consul['services'] = %w(postgresql)
+
+ # Specify if a node should attempt to be primary on initialization.
+ repmgr['master_on_initialization'] = false
+
+ # START user configuration
+ # Please set the real values as explained in Required Information section
+ #
+ # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
+ postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>'
+ # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
+ postgresql['sql_user_password'] = '<postgresql_password_hash>'
+ # Set `max_wal_senders` to one more than the number of database nodes in the cluster.
+ # This is used to prevent replication from using up all of the
+ # available database connections.
+ postgresql['max_wal_senders'] = 4
+ postgresql['max_replication_slots'] = 4
+
+ # Replace XXX.XXX.XXX.XXX/YY with Network Address
+ postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24)
+ repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24)
+
+ ## Enable service discovery for Prometheus
+ consul['enable'] = true
+ consul['monitoring_service_discovery'] = true
+
+ # Set the network addresses that the exporters will listen on for monitoring
+ node_exporter['listen_address'] = '0.0.0.0:9100'
+ postgres_exporter['listen_address'] = '0.0.0.0:9187'
+ postgres_exporter['dbname'] = 'gitlabhq_production'
+ postgres_exporter['password'] = '<postgresql_password_hash>'
+
+ ## The IPs of the Consul server nodes
+ ## You can also use FQDNs and intermix them with IPs
+ consul['configuration'] = {
+ retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13),
+ }
+ # END user configuration
+ ```
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
+Advanced [configuration options](https://docs.gitlab.com/omnibus/settings/database.html)
+are supported and can be added if needed.
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#setup-components">
+ Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+#### PostgreSQL post-configuration
+
+SSH into the **primary node**:
+
+1. Open a database prompt:
+
+ ```shell
+ gitlab-psql -d gitlabhq_production
+ ```
+
+1. Enable the `pg_trgm` extension:
+
+ ```shell
+ CREATE EXTENSION pg_trgm;
+ ```
+
+1. Exit the database prompt by typing `\q` and Enter.
+
+1. Verify the cluster is initialized with one node:
+
+ ```shell
+ gitlab-ctl repmgr cluster show
+ ```
+
+ The output should be similar to the following:
+
+ ```plaintext
+ Role | Name | Upstream | Connection String
+ ----------+----------|----------|----------------------------------------
+ * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr
+ ```
+
+1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will
+ refer to the hostname in the next section as `<primary_node_name>`. If the value
+ is not an IP address, it will need to be a resolvable name (via DNS or
+ `/etc/hosts`)
+
+SSH into the **secondary node**:
+
+1. Set up the repmgr standby:
+
+ ```shell
+ gitlab-ctl repmgr standby setup <primary_node_name>
+ ```
+
+ Do note that this will remove the existing data on the node. The command
+ has a wait time.
+
+ The output should be similar to the following:
+
+ ```console
+ Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data
+ If this is not what you want, hit Ctrl-C now to exit
+ To skip waiting, rerun with the -w option
+ Sleeping for 30 seconds
+ Stopping the database
+ Removing the data
+ Cloning the data
+ Starting the database
+ Registering the node with the cluster
+ ok: run: repmgrd: (pid 19068) 0s
+ ```
+
+Before moving on, make sure the databases are configured correctly. Run the
+following command on the **primary** node to verify that replication is working
+properly and the secondary nodes appear in the cluster:
+
+```shell
+gitlab-ctl repmgr cluster show
+```
+
+The output should be similar to the following:
+
+```plaintext
+Role | Name | Upstream | Connection String
+----------+---------|-----------|------------------------------------------------
+* master | MASTER | | host=<primary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr
+ standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr
+ standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr
+```
+
+If the 'Role' column for any node says "FAILED", check the
+[Troubleshooting section](troubleshooting.md) before proceeding.
+
+Also, check that the `repmgr-check-master` command works successfully on each node:
+
+```shell
+su - gitlab-consul
+gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node'
+```
+
+This command relies on exit codes to tell Consul whether a particular node is a master
+or secondary. The most important thing here is that this command does not produce errors.
+If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions.
+Check the [Troubleshooting section](troubleshooting.md) before proceeding.
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#setup-components">
+ Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+## Configure PgBouncer
+
+Now that the PostgreSQL servers are all set up, let's configure PgBouncer.
+The following IPs will be used as an example:
+
+- `10.6.0.21`: PgBouncer 1
+- `10.6.0.22`: PgBouncer 2
+- `10.6.0.23`: PgBouncer 3
+
+1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`, and replace
+ `<consul_password_hash>` and `<pgbouncer_password_hash>` with the
+ password hashes you [set up previously](#postgresql-primary-node):
+
+ ```ruby
+ # Disable all components except Pgbouncer and Consul agent
+ roles ['pgbouncer_role']
+
+ # Configure PgBouncer
+ pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
+
+ pgbouncer['users'] = {
+ 'gitlab-consul': {
+ password: '<consul_password_hash>'
+ },
+ 'pgbouncer': {
+ password: '<pgbouncer_password_hash>'
+ }
+ }
+
+ # Configure Consul agent
+ consul['watchers'] = %w(postgresql)
+ consul['enable'] = true
+ consul['configuration'] = {
+ retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
+ }
+
+ # Enable service discovery for Prometheus
+ consul['monitoring_service_discovery'] = true
+
+ # Set the network addresses that the exporters will listen on
+ node_exporter['listen_address'] = '0.0.0.0:9100'
+ pgbouncer_exporter['listen_address'] = '0.0.0.0:9188'
+ ```
+
+1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
+1. Create a `.pgpass` file so Consul is able to
+ reload PgBouncer. Enter the PgBouncer password twice when asked:
+
+ ```shell
+ gitlab-ctl write-pgpass --host 127.0.0.1 --database pgbouncer --user pgbouncer --hostuser gitlab-consul
+ ```
+
+1. Ensure each node is talking to the current master:
+
+ ```shell
+ gitlab-ctl pgb-console # You will be prompted for PGBOUNCER_PASSWORD
+ ```
+
+ If there is an error `psql: ERROR: Auth failed` after typing in the
+ password, ensure you previously generated the MD5 password hashes with the correct
+ format. The correct format is to concatenate the password and the username:
+ `PASSWORDUSERNAME`. For example, `Sup3rS3cr3tpgbouncer` would be the text
+ needed to generate an MD5 password hash for the `pgbouncer` user.
+
+1. Once the console prompt is available, run the following queries:
+
+ ```shell
+ show databases ; show clients ;
+ ```
+
+ The output should be similar to the following:
+
+ ```plaintext
+ name | host | port | database | force_user | pool_size | reserve_pool | pool_mode | max_connections | current_connections
+ ---------------------+-------------+------+---------------------+------------+-----------+--------------+-----------+-----------------+---------------------
+ gitlabhq_production | MASTER_HOST | 5432 | gitlabhq_production | | 20 | 0 | | 0 | 0
+ pgbouncer | | 6432 | pgbouncer | pgbouncer | 2 | 0 | statement | 0 | 0
+ (2 rows)
+
+ type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link | remote_pid | tls
+ ------+-----------+---------------------+---------+----------------+-------+------------+------------+---------------------+---------------------+-----------+------+------------+-----
+ C | pgbouncer | pgbouncer | active | 127.0.0.1 | 56846 | 127.0.0.1 | 6432 | 2017-08-21 18:09:59 | 2017-08-21 18:10:48 | 0x22b3880 | | 0 |
+ (2 rows)
+ ```
+
+1. Verify the GitLab services are running:
+
+ ```shell
+ sudo gitlab-ctl status
+ ```
+
+ The output should be similar to the following:
+
+ ```plaintext
+ run: consul: (pid 31530) 77150s; run: log: (pid 31106) 77182s
+ run: logrotate: (pid 32613) 3357s; run: log: (pid 30107) 77500s
+ run: node-exporter: (pid 31550) 77149s; run: log: (pid 30138) 77493s
+ run: pgbouncer: (pid 32033) 75593s; run: log: (pid 31117) 77175s
+ run: pgbouncer-exporter: (pid 31558) 77148s; run: log: (pid 31498) 77156s
+ ```
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#setup-components">
+ Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+### Configure the internal load balancer
+
+If you're running more than one PgBouncer node as recommended, then at this time you'll need to set
+up a TCP internal load balancer to serve each correctly.
+
+The following IP will be used as an example:
+
+- `10.6.0.20`: Internal Load Balancer
+
+Here's how you could do it with [HAProxy](https://www.haproxy.org/):
+
+```plaintext
+global
+ log /dev/log local0
+ log localhost local1 notice
+ log stdout format raw local0
+
+defaults
+ log global
+ default-server inter 10s fall 3 rise 2
+ balance leastconn
+
+frontend internal-pgbouncer-tcp-in
+ bind *:6432
+ mode tcp
+ option tcplog
+
+ default_backend pgbouncer
+
+backend pgbouncer
+ mode tcp
+ option tcp-check
+
+ server pgbouncer1 10.6.0.21:6432 check
+ server pgbouncer2 10.6.0.22:6432 check
+ server pgbouncer3 10.6.0.23:6432 check
+```
+
+Refer to your preferred Load Balancer's documentation for further guidance.
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#setup-components">
+ Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+## Configure Gitaly
+
+Deploying Gitaly in its own server can benefit GitLab installations that are
+larger than a single machine.
+
+The Gitaly node requirements are dependent on customer data, specifically the number of
+projects and their repository sizes. Two nodes are recommended as an absolute minimum.
+Each Gitaly node should store no more than 5TB of data and have the number of
+[`gitaly-ruby` workers](../gitaly/index.md#gitaly-ruby) set to 20% of available CPUs.
+Additional nodes should be considered in conjunction with a review of expected
+data size and spread based on the recommendations above.
+
+It is also strongly recommended that all Gitaly nodes be set up with SSD disks with
+a throughput of at least 8,000 IOPS for read operations and 2,000 IOPS for write,
+as Gitaly has heavy I/O. These IOPS values are recommended only as a starter as with
+time they may be adjusted higher or lower depending on the scale of your environment's workload.
+If you're running the environment on a Cloud provider, you may need to refer to
+their documentation on how to configure IOPS correctly.
+
+Some things to note:
+
+- The GitLab Rails application shards repositories into [repository storages](../repository_storage_paths.md).
+- A Gitaly server can host one or more storages.
+- A GitLab server can use one or more Gitaly servers.
+- Gitaly addresses must be specified in such a way that they resolve
+ correctly for ALL Gitaly clients.
+- Gitaly servers must not be exposed to the public internet, as Gitaly's network
+ traffic is unencrypted by default. The use of a firewall is highly recommended
+ to restrict access to the Gitaly server. Another option is to
+ [use TLS](#gitaly-tls-support).
+
+TIP: **Tip:**
+For more information about Gitaly's history and network architecture see the
+[standalone Gitaly documentation](../gitaly/index.md).
+
+Note: **Note:** The token referred to throughout the Gitaly documentation is
+just an arbitrary password selected by the administrator. It is unrelated to
+tokens created for the GitLab API or other similar web API tokens.
+
+Below we describe how to configure two Gitaly servers, with IPs and
+domain names:
+
+- `10.6.0.51`: Gitaly 1 (`gitaly1.internal`)
+- `10.6.0.52`: Gitaly 2 (`gitaly2.internal`)
+
+The secret token is assumed to be `gitalysecret` and that
+your GitLab installation has three repository storages:
+
+- `default` on Gitaly 1
+- `storage1` on Gitaly 1
+- `storage2` on Gitaly 2
+
+On each node:
+
+1. [Download/Install](https://about.gitlab.com/install/) the Omnibus GitLab
+ package you want using **steps 1 and 2** from the GitLab downloads page but
+ **without** providing the `EXTERNAL_URL` value.
+1. Edit `/etc/gitlab/gitlab.rb` to configure storage paths, enable
+ the network listener and configure the token:
+
+ <!--
+ updates to following example must also be made at
+ https://gitlab.com/gitlab-org/charts/gitlab/blob/master/doc/advanced/external-gitaly/external-omnibus-gitaly.md#configure-omnibus-gitlab
+ -->
+
+ ```ruby
+ # /etc/gitlab/gitlab.rb
+
+ # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests
+ # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API.
+ # The following two values must be the same as their respective values
+ # of the GitLab Rails application setup
+ gitaly['auth_token'] = 'gitlaysecret'
+ gitlab_shell['secret_token'] = 'shellsecret'
+
+ # Avoid running unnecessary services on the Gitaly server
+ postgresql['enable'] = false
+ redis['enable'] = false
+ nginx['enable'] = false
+ puma['enable'] = false
+ unicorn['enable'] = false
+ sidekiq['enable'] = false
+ gitlab_workhorse['enable'] = false
+ grafana['enable'] = false
+ gitlab_exporter['enable'] = false
+
+ # If you run a seperate monitoring node you can disable these services
+ alertmanager['enable'] = false
+ prometheus['enable'] = false
+
+ # Prevent database connections during 'gitlab-ctl reconfigure'
+ gitlab_rails['rake_cache_clear'] = false
+ gitlab_rails['auto_migrate'] = false
+
+ # Configure the gitlab-shell API callback URL. Without this, `git push` will
+ # fail. This can be your 'front door' GitLab URL or an internal load
+ # balancer.
+ # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from web server to Gitaly server.
+ gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
+
+ # Make Gitaly accept connections on all network interfaces. You must use
+ # firewalls to restrict access to this address/port.
+ # Comment out following line if you only want to support TLS connections
+ gitaly['listen_addr'] = "0.0.0.0:8075"
+
+ ## Enable service discovery for Prometheus
+ consul['enable'] = true
+ consul['monitoring_service_discovery'] = true
+
+ # Set the network addresses that the exporters will listen on for monitoring
+ gitaly['prometheus_listen_addr'] = "0.0.0.0:9236"
+ node_exporter['listen_address'] = '0.0.0.0:9100'
+ gitlab_rails['prometheus_address'] = '10.6.0.81:9090'
+
+ ## The IPs of the Consul server nodes
+ ## You can also use FQDNs and intermix them with IPs
+ consul['configuration'] = {
+ retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13),
+ }
+ ```
+
+1. Append the following to `/etc/gitlab/gitlab.rb` for each respective server:
+ 1. On `gitaly1.internal`:
+
+ ```ruby
+ git_data_dirs({
+ 'default' => {
+ 'path' => '/var/opt/gitlab/git-data'
+ },
+ 'storage1' => {
+ 'path' => '/mnt/gitlab/git-data'
+ },
+ })
+ ```
+
+ 1. On `gitaly2.internal`:
+
+ ```ruby
+ git_data_dirs({
+ 'storage2' => {
+ 'path' => '/mnt/gitlab/git-data'
+ },
+ })
+ ```
+
+ <!--
+ updates to following example must also be made at
+ https://gitlab.com/gitlab-org/charts/gitlab/blob/master/doc/advanced/external-gitaly/external-omnibus-gitaly.md#configure-omnibus-gitlab
+ -->
+
+1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. Confirm that Gitaly can perform callbacks to the internal API:
+
+ ```shell
+ sudo /opt/gitlab/embedded/service/gitlab-shell/bin/check -config /opt/gitlab/embedded/service/gitlab-shell/config.yml
+ ```
+
+1. Verify the GitLab services are running:
+
+ ```shell
+ sudo gitlab-ctl status
+ ```
+
+ The output should be similar to the following:
+
+ ```plaintext
+ run: consul: (pid 30339) 77006s; run: log: (pid 29878) 77020s
+ run: gitaly: (pid 30351) 77005s; run: log: (pid 29660) 77040s
+ run: logrotate: (pid 7760) 3213s; run: log: (pid 29782) 77032s
+ run: node-exporter: (pid 30378) 77004s; run: log: (pid 29812) 77026s
+ ```
+
+### Gitaly TLS support
+
+Gitaly supports TLS encryption. To be able to communicate
+with a Gitaly instance that listens for secure connections you will need to use `tls://` URL
+scheme in the `gitaly_address` of the corresponding storage entry in the GitLab configuration.
+
+You will need to bring your own certificates as this isn't provided automatically.
+The certificate, or its certificate authority, must be installed on all Gitaly
+nodes (including the Gitaly node using the certificate) and on all client nodes
+that communicate with it following the procedure described in
+[GitLab custom certificate configuration](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates).
+
+NOTE: **Note:**
+The self-signed certificate must specify the address you use to access the
+Gitaly server. If you are addressing the Gitaly server by a hostname, you can
+either use the Common Name field for this, or add it as a Subject Alternative
+Name. If you are addressing the Gitaly server by its IP address, you must add it
+as a Subject Alternative Name to the certificate.
+[gRPC does not support using an IP address as Common Name in a certificate](https://github.com/grpc/grpc/issues/2691).
+
+NOTE: **Note:**
+It is possible to configure Gitaly servers with both an
+unencrypted listening address `listen_addr` and an encrypted listening
+address `tls_listen_addr` at the same time. This allows you to do a
+gradual transition from unencrypted to encrypted traffic, if necessary.
+
+To configure Gitaly with TLS:
+
+1. Create the `/etc/gitlab/ssl` directory and copy your key and certificate there:
+
+ ```shell
+ sudo mkdir -p /etc/gitlab/ssl
+ sudo chmod 755 /etc/gitlab/ssl
+ sudo cp key.pem cert.pem /etc/gitlab/ssl/
+ sudo chmod 644 key.pem cert.pem
+ ```
+
+1. Copy the cert to `/etc/gitlab/trusted-certs` so Gitaly will trust the cert when
+ calling into itself:
+
+ ```shell
+ sudo cp /etc/gitlab/ssl/cert.pem /etc/gitlab/trusted-certs/
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` and add:
+
+ <!--
+ updates to following example must also be made at
+ https://gitlab.com/gitlab-org/charts/gitlab/blob/master/doc/advanced/external-gitaly/external-omnibus-gitaly.md#configure-omnibus-gitlab
+ -->
+
+ ```ruby
+ gitaly['tls_listen_addr'] = "0.0.0.0:9999"
+ gitaly['certificate_path'] = "/etc/gitlab/ssl/cert.pem"
+ gitaly['key_path'] = "/etc/gitlab/ssl/key.pem"
+ ```
+
+1. Delete `gitaly['listen_addr']` to allow only encrypted connections.
+1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#setup-components">
+ Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+## Configure Sidekiq
+
+Sidekiq requires connection to the Redis, PostgreSQL and Gitaly instance.
+The following IPs will be used as an example:
+
+- `10.6.0.71`: Sidekiq 1
+- `10.6.0.72`: Sidekiq 2
+- `10.6.0.73`: Sidekiq 3
+- `10.6.0.74`: Sidekiq 4
+
+To configure the Sidekiq nodes, one each one:
+
+1. SSH into the Sidekiq server.
+1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab package
+you want using steps 1 and 2 from the GitLab downloads page.
+**Do not complete any other steps on the download page.**
+1. Open `/etc/gitlab/gitlab.rb` with your editor:
+
+ ```ruby
+ ########################################
+ ##### Services Disabled ###
+ ########################################
+
+ nginx['enable'] = false
+ grafana['enable'] = false
+ prometheus['enable'] = false
+ gitlab_rails['auto_migrate'] = false
+ alertmanager['enable'] = false
+ gitaly['enable'] = false
+ gitlab_workhorse['enable'] = false
+ nginx['enable'] = false
+ puma['enable'] = false
+ postgres_exporter['enable'] = false
+ postgresql['enable'] = false
+ redis['enable'] = false
+ redis_exporter['enable'] = false
+ gitlab_exporter['enable'] = false
+
+ ########################################
+ #### Redis ###
+ ########################################
+
+ ## Must be the same in every sentinel node
+ redis['master_name'] = 'gitlab-redis'
+
+ ## The same password for Redis authentication you set up for the master node.
+ redis['master_password'] = '<redis_primary_password>'
+
+ ## A list of sentinels with `host` and `port`
+ gitlab_rails['redis_sentinels'] = [
+ {'host' => '10.6.0.11', 'port' => 26379},
+ {'host' => '10.6.0.12', 'port' => 26379},
+ {'host' => '10.6.0.13', 'port' => 26379},
+ ]
+
+ #######################################
+ ### Gitaly ###
+ #######################################
+
+ git_data_dirs({
+ 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
+ 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
+ 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' },
+ })
+ gitlab_rails['gitaly_token'] = 'YOUR_TOKEN'
+
+ #######################################
+ ### Postgres ###
+ #######################################
+ gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP
+ gitlab_rails['db_port'] = 6432
+ gitlab_rails['db_password'] = '<postgresql_user_password>'
+ gitlab_rails['db_adapter'] = 'postgresql'
+ gitlab_rails['db_encoding'] = 'unicode'
+ gitlab_rails['auto_migrate'] = false
+
+ #######################################
+ ### Sidekiq configuration ###
+ #######################################
+ sidekiq['listen_address'] = "0.0.0.0"
+
+ #######################################
+ ### Monitoring configuration ###
+ #######################################
+ consul['enable'] = true
+ consul['monitoring_service_discovery'] = true
+
+ consul['configuration'] = {
+ retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
+ }
+
+ # Set the network addresses that the exporters will listen on
+ node_exporter['listen_address'] = '0.0.0.0:9100'
+
+ # Rails Status for prometheus
+ gitlab_rails['monitoring_whitelist'] = ['10.6.0.81/32', '127.0.0.0/8']
+ gitlab_rails['prometheus_address'] = '10.6.0.81:9090'
+ ```
+
+1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. Verify the GitLab services are running:
+
+ ```shell
+ sudo gitlab-ctl status
+ ```
+
+ The output should be similar to the following:
+
+ ```plaintext
+ run: consul: (pid 30114) 77353s; run: log: (pid 29756) 77367s
+ run: logrotate: (pid 9898) 3561s; run: log: (pid 29653) 77380s
+ run: node-exporter: (pid 30134) 77353s; run: log: (pid 29706) 77372s
+ run: sidekiq: (pid 30142) 77351s; run: log: (pid 29638) 77386s
+ ```
+
+TIP: **Tip:**
+You can also run [multiple Sidekiq processes](../operations/extra_sidekiq_processes.md).
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#setup-components">
+ Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+## Configure GitLab Rails
+
+NOTE: **Note:**
+In our architectures we run each GitLab Rails node using the Puma webserver
+and have its number of workers set to 90% of available CPUs along with four threads. For
+nodes that are running Rails with other components the worker value should be reduced
+accordingly where we've found 50% achieves a good balance but this is dependent
+on workload.
+
+This section describes how to configure the GitLab application (Rails) component.
+On each node perform the following:
+
+1. If you're [using NFS](#configure-nfs-optional):
+
+ 1. If necessary, install the NFS client utility packages using the following
+ commands:
+
+ ```shell
+ # Ubuntu/Debian
+ apt-get install nfs-common
+
+ # CentOS/Red Hat
+ yum install nfs-utils nfs-utils-lib
+ ```
+
+ 1. Specify the necessary NFS mounts in `/etc/fstab`.
+ The exact contents of `/etc/fstab` will depend on how you chose
+ to configure your NFS server. See the [NFS documentation](../high_availability/nfs.md)
+ for examples and the various options.
+
+ 1. Create the shared directories. These may be different depending on your NFS
+ mount locations.
+
+ ```shell
+ mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data
+ ```
+
+1. Download/install Omnibus GitLab using **steps 1 and 2** from
+ [GitLab downloads](https://about.gitlab.com/install/). Do not complete other
+ steps on the download page.
+1. Create/edit `/etc/gitlab/gitlab.rb` and use the following configuration.
+ To maintain uniformity of links across nodes, the `external_url`
+ on the application server should point to the external URL that users will use
+ to access GitLab. This would be the URL of the [external load balancer](#configure-the-external-load-balancer)
+ which will route traffic to the GitLab application server:
+
+ ```ruby
+ external_url 'https://gitlab.example.com'
+
+ # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests
+ # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API.
+ # The following two values must be the same as their respective values
+ # of the Gitaly setup
+ gitlab_rails['gitaly_token'] = 'gitalyecret'
+ gitlab_shell['secret_token'] = 'shellsecret'
+
+ git_data_dirs({
+ 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
+ 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
+ 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' },
+ })
+
+ ## Disable components that will not be on the GitLab application server
+ roles ['application_role']
+ gitaly['enable'] = false
+ nginx['enable'] = true
+ sidekiq['enable'] = false
+
+ ## PostgreSQL connection details
+ # Disable PostgreSQL on the application node
+ postgresql['enable'] = false
+ gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP
+ gitlab_rails['db_port'] = 6432
+ gitlab_rails['db_password'] = '<postgresql_user_password>'
+ gitlab_rails['auto_migrate'] = false
+
+ ## Redis connection details
+ ## Must be the same in every sentinel node
+ redis['master_name'] = 'gitlab-redis'
+
+ ## The same password for Redis authentication you set up for the Redis primary node.
+ redis['master_password'] = '<redis_primary_password>'
+
+ ## A list of sentinels with `host` and `port`
+ gitlab_rails['redis_sentinels'] = [
+ {'host' => '10.6.0.11', 'port' => 26379},
+ {'host' => '10.6.0.12', 'port' => 26379},
+ {'host' => '10.6.0.13', 'port' => 26379}
+ ]
+
+ ## Enable service discovery for Prometheus
+ consul['enable'] = true
+ consul['monitoring_service_discovery'] = true
+
+ # Set the network addresses that the exporters used for monitoring will listen on
+ node_exporter['listen_address'] = '0.0.0.0:9100'
+ gitlab_workhorse['prometheus_listen_addr'] = '0.0.0.0:9229'
+ sidekiq['listen_address'] = "0.0.0.0"
+ puma['listen'] = '0.0.0.0'
+
+ ## The IPs of the Consul server nodes
+ ## You can also use FQDNs and intermix them with IPs
+ consul['configuration'] = {
+ retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13),
+ }
+
+ # Add the monitoring node's IP address to the monitoring whitelist and allow it to
+ # scrape the NGINX metrics
+ gitlab_rails['monitoring_whitelist'] = ['10.6.0.81/32', '127.0.0.0/8']
+ nginx['status']['options']['allow'] = ['10.6.0.81/32', '127.0.0.0/8']
+ gitlab_rails['prometheus_address'] = '10.6.0.81:9090'
+
+ ## Uncomment and edit the following options if you have set up NFS
+ ##
+ ## Prevent GitLab from starting if NFS data mounts are not available
+ ##
+ #high_availability['mountpoint'] = '/var/opt/gitlab/git-data'
+ ##
+ ## Ensure UIDs and GIDs match between servers for permissions via NFS
+ ##
+ #user['uid'] = 9000
+ #user['gid'] = 9000
+ #web_server['uid'] = 9001
+ #web_server['gid'] = 9001
+ #registry['uid'] = 9002
+ #registry['gid'] = 9002
+ ```
+
+1. If you're using [Gitaly with TLS support](#gitaly-tls-support), make sure the
+ `git_data_dirs` entry is configured with `tls` instead of `tcp`:
+
+ ```ruby
+ git_data_dirs({
+ 'default' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' },
+ 'storage1' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' },
+ 'storage2' => { 'gitaly_address' => 'tls://gitaly2.internal:9999' },
+ })
+ ```
+
+ 1. Copy the cert into `/etc/gitlab/trusted-certs`:
+
+ ```shell
+ sudo cp cert.pem /etc/gitlab/trusted-certs/
+ ```
+
+1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. Run `sudo gitlab-rake gitlab:gitaly:check` to confirm the node can connect to Gitaly.
+1. Tail the logs to see the requests:
+
+ ```shell
+ sudo gitlab-ctl tail gitaly
+ ```
+
+1. Verify the GitLab services are running:
+
+ ```shell
+ sudo gitlab-ctl status
+ ```
+
+ The output should be similar to the following:
+
+ ```plaintext
+ run: consul: (pid 4890) 8647s; run: log: (pid 29962) 79128s
+ run: gitlab-exporter: (pid 4902) 8647s; run: log: (pid 29913) 79134s
+ run: gitlab-workhorse: (pid 4904) 8646s; run: log: (pid 29713) 79155s
+ run: logrotate: (pid 12425) 1446s; run: log: (pid 29798) 79146s
+ run: nginx: (pid 4925) 8646s; run: log: (pid 29726) 79152s
+ run: node-exporter: (pid 4931) 8645s; run: log: (pid 29855) 79140s
+ run: puma: (pid 4936) 8645s; run: log: (pid 29656) 79161s
+ ```
+
+NOTE: **Note:**
+When you specify `https` in the `external_url`, as in the example
+above, GitLab assumes you have SSL certificates in `/etc/gitlab/ssl/`. If
+certificates are not present, NGINX will fail to start. See the
+[NGINX documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
+for more information.
+
+### GitLab Rails post-configuration
+
+1. Ensure that all migrations ran:
+
+ ```shell
+ gitlab-rake gitlab:db:configure
+ ```
+
+ NOTE: **Note:**
+ If you encounter a `rake aborted!` error stating that PgBouncer is failing to connect to
+ PostgreSQL it may be that your PgBouncer node's IP address is missing from
+ PostgreSQL's `trust_auth_cidr_addresses` in `gitlab.rb` on your database nodes. See
+ [PgBouncer error `ERROR: pgbouncer cannot connect to server`](troubleshooting.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server)
+ in the Troubleshooting section before proceeding.
+
+1. [Configure fast lookup of authorized SSH keys in the database](../operations/fast_ssh_key_lookup.md).
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#setup-components">
+ Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+## Configure Prometheus
+
+The Omnibus GitLab package can be used to configure a standalone Monitoring node
+running [Prometheus](../monitoring/prometheus/index.md) and
+[Grafana](../monitoring/performance/grafana_configuration.md):
+
+1. SSH into the Monitoring node.
+1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab
+ package you want using **steps 1 and 2** from the GitLab downloads page.
+ Do not complete any other steps on the download page.
+1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
+
+ ```ruby
+ external_url 'http://gitlab.example.com'
+
+ # Disable all other services
+ gitlab_rails['auto_migrate'] = false
+ alertmanager['enable'] = false
+ gitaly['enable'] = false
+ gitlab_exporter['enable'] = false
+ gitlab_workhorse['enable'] = false
+ nginx['enable'] = true
+ postgres_exporter['enable'] = false
+ postgresql['enable'] = false
+ redis['enable'] = false
+ redis_exporter['enable'] = false
+ sidekiq['enable'] = false
+ puma['enable'] = false
+ unicorn['enable'] = false
+ node_exporter['enable'] = false
+ gitlab_exporter['enable'] = false
+
+ # Enable Prometheus
+ prometheus['enable'] = true
+ prometheus['listen_address'] = '0.0.0.0:9090'
+ prometheus['monitor_kubernetes'] = false
+
+ # Enable Login form
+ grafana['disable_login_form'] = false
+
+ # Enable Grafana
+ grafana['enable'] = true
+ grafana['admin_password'] = '<grafana_password>'
+
+ # Enable service discovery for Prometheus
+ consul['enable'] = true
+ consul['monitoring_service_discovery'] = true
+ consul['configuration'] = {
+ retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
+ }
+ ```
+
+1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. In the GitLab UI, set `admin/application_settings/metrics_and_profiling` > Metrics - Grafana to `/-/grafana` to
+ `http[s]://<MONITOR NODE>/-/grafana`.
+1. Verify the GitLab services are running:
+
+ ```shell
+ sudo gitlab-ctl status
+ ```
+
+ The output should be similar to the following:
+
+ ```plaintext
+ run: consul: (pid 31637) 17337s; run: log: (pid 29748) 78432s
+ run: grafana: (pid 31644) 17337s; run: log: (pid 29719) 78438s
+ run: logrotate: (pid 31809) 2936s; run: log: (pid 29581) 78462s
+ run: nginx: (pid 31665) 17335s; run: log: (pid 29556) 78468s
+ run: prometheus: (pid 31672) 17335s; run: log: (pid 29633) 78456s
+ ```
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#setup-components">
+ Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+## Configure the object storage
+
+GitLab supports using an object storage service for holding numerous types of data.
+It's recommended over [NFS](#configure-nfs-optional) and in general it's better
+in larger setups as object storage is typically much more performant, reliable,
+and scalable.
+
+Object storage options that GitLab has tested, or is aware of customers using include:
+
+- SaaS/Cloud solutions such as [Amazon S3](https://aws.amazon.com/s3/), [Google cloud storage](https://cloud.google.com/storage).
+- On-premises hardware and appliances from various storage vendors.
+- MinIO. There is [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.
+
+For configuring GitLab to use Object Storage refer to the following guides
+based on what features you intend to use:
+
+1. Configure [object storage for backups](../../raketasks/backup_restore.md#uploading-backups-to-a-remote-cloud-storage).
+1. Configure [object storage for job artifacts](../job_artifacts.md#using-object-storage)
+ including [incremental logging](../job_logs.md#new-incremental-logging-architecture).
+1. Configure [object storage for LFS objects](../lfs/index.md#storing-lfs-objects-in-remote-object-storage).
+1. Configure [object storage for uploads](../uploads.md#using-object-storage-core-only).
+1. Configure [object storage for merge request diffs](../merge_request_diffs.md#using-object-storage).
+1. Configure [object storage for Container Registry](../packages/container_registry.md#use-object-storage) (optional feature).
+1. Configure [object storage for Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage) (optional feature).
+1. Configure [object storage for packages](../packages/index.md#using-object-storage) (optional feature). **(PREMIUM ONLY)**
+1. Configure [object storage for Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature). **(PREMIUM ONLY)**
+1. Configure [object storage for Pseudonymizer](../pseudonymizer.md#configuration) (optional feature). **(ULTIMATE ONLY)**
+1. Configure [object storage for autoscale Runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional - for improved performance).
+1. Configure [object storage for Terraform state files](../terraform_state.md#using-object-storage-core-only).
+
+Using separate buckets for each data type is the recommended approach for GitLab.
+
+A limitation of our configuration is that each use of object storage is separately configured.
+[We have an issue for improving this](https://gitlab.com/gitlab-org/gitlab/-/issues/23345)
+and easily using one bucket with separate folders is one improvement that this might bring.
+
+There is at least one specific issue with using the same bucket:
+when GitLab is deployed with the Helm chart restore from backup
+[will not properly function](https://docs.gitlab.com/charts/advanced/external-object-storage/#lfs-artifacts-uploads-packages-external-diffs-pseudonymizer)
+unless separate buckets are used.
+
+One risk of using a single bucket would be if your organization decided to
+migrate GitLab to the Helm deployment in the future. GitLab would run, but the situation with
+backups might not be realized until the organization had a critical requirement for the backups to
+work.
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#setup-components">
+ Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+## Configure NFS (optional)
+
+[Object storage](#configure-the-object-storage), along with [Gitaly](#configure-gitaly)
+are recommended over NFS wherever possible for improved performance. If you intend
+to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pages-requires-nfs).
+
+See how to [configure NFS](../high_availability/nfs.md).
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#setup-components">
+ Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+## Troubleshooting
+
+See the [troubleshooting documentation](troubleshooting.md).
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#setup-components">
+ Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
diff --git a/doc/administration/snippets/index.md b/doc/administration/snippets/index.md
index cf3d8bec1a6..1e4679d3a1d 100644
--- a/doc/administration/snippets/index.md
+++ b/doc/administration/snippets/index.md
@@ -1,5 +1,8 @@
---
type: reference, howto
+stage: Create
+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/#designated-technical-writers
---
# Snippets settings **(CORE ONLY)**
@@ -10,15 +13,15 @@ Adjust the snippets' settings of your GitLab instance.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31133) in GitLab 12.6.
-You can set a content size max limit in snippets. This limit can prevent
-abuses of the feature. The default content size limit is **52428800 Bytes** (50MB).
+You can set a maximum content size limit for snippets. This limit can prevent
+abuse of the feature. The default value is **52428800 Bytes** (50 MB).
### How does it work?
-The content size limit will be applied when a snippet is created or
-updated. Nevertheless, in order not to break any existing snippet,
-the limit will only be enforced in stored snippets when the content
-is updated.
+The content size limit will be applied when a snippet is created or updated.
+
+In order not to break any existing snippets, the limit doesn't have any
+effect on them until a snippet is edited again and the content changes.
### Snippets size limit configuration
@@ -27,7 +30,7 @@ In order to configure this setting, use either the Rails console
or the [Application settings API](../../api/settings.md).
NOTE: **IMPORTANT:**
-The value of the limit **must** be in Bytes.
+The value of the limit **must** be in bytes.
#### Through the Rails console
diff --git a/doc/administration/wikis/index.md b/doc/administration/wikis/index.md
new file mode 100644
index 00000000000..b6dfd07cab0
--- /dev/null
+++ b/doc/administration/wikis/index.md
@@ -0,0 +1,75 @@
+---
+type: reference, howto
+stage: Create
+group: Knowledge
+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/#designated-technical-writers
+---
+
+# Wiki settings **(CORE ONLY)**
+
+Adjust the wiki settings of your GitLab instance.
+
+## Wiki page content size limit
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31176) in GitLab 13.2.
+
+You can set a maximum content size limit for wiki pages. This limit can prevent
+abuse of the feature. The default value is **52428800 Bytes** (50 MB).
+
+### How does it work?
+
+The content size limit will be applied when a wiki page is created or updated
+through the GitLab UI or API. Local changes pushed via Git will not be validated.
+
+In order not to break any existing wiki pages, the limit doesn't have any
+effect on them until a wiki page is edited again and the content changes.
+
+### Wiki page content size limit configuration
+
+This setting is not available through the [Admin Area settings](../../user/admin_area/settings/index.md).
+In order to configure this setting, use either the Rails console
+or the [Application settings API](../../api/settings.md).
+
+NOTE: **IMPORTANT:**
+The value of the limit **must** be in bytes.
+
+#### Through the Rails console
+
+The steps to configure this setting through the Rails console are:
+
+1. Start the Rails console:
+
+ ```shell
+ # For Omnibus installations
+ sudo gitlab-rails console
+
+ # For installations from source
+ sudo -u git -H bundle exec rails console -e production
+ ```
+
+1. Update the wiki page maximum content size:
+
+ ```ruby
+ ApplicationSetting.first.update!(wiki_page_max_content_bytes: 50.megabytes)
+ ```
+
+To retrieve the current value, start the Rails console and run:
+
+ ```ruby
+ Gitlab::CurrentSettings.wiki_page_max_content_bytes
+ ```
+
+#### Through the API
+
+The process to set the wiki page size limit through the Application Settings API is
+exactly the same as you would do to [update any other setting](../../api/settings.md#change-application-settings).
+
+```shell
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/application/settings?wiki_page_max_content_bytes=52428800
+```
+
+You can also use the API to [retrieve the current value](../../api/settings.md#get-current-application-settings).
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/application/settings
+```
diff --git a/doc/api/settings.md b/doc/api/settings.md
index d87a3c72a7e..ff4ee91d858 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -71,8 +71,10 @@ Example response:
"asset_proxy_url": "https://assets.example.com",
"asset_proxy_whitelist": ["example.com", "*.example.com", "your-instance.com"],
"npm_package_requests_forwarding": true,
+ "snippet_size_limit": 52428800,
"issues_create_limit": 300,
- "raw_blob_request_limit": 300
+ "raw_blob_request_limit": 300,
+ "wiki_page_max_content_bytes": 52428800
}
```
@@ -161,8 +163,10 @@ Example response:
"allow_local_requests_from_web_hooks_and_services": true,
"allow_local_requests_from_system_hooks": false,
"npm_package_requests_forwarding": true,
+ "snippet_size_limit": 52428800,
"issues_create_limit": 300,
- "raw_blob_request_limit": 300
+ "raw_blob_request_limit": 300,
+ "wiki_page_max_content_bytes": 52428800
}
```
@@ -369,3 +373,4 @@ are listed in the descriptions of the relevant settings.
| `snippet_size_limit` | integer | no | Max snippet content size in **bytes**. Default: 52428800 Bytes (50MB).|
| `issues_create_limit` | integer | no | Max number of issue creation requests per minute per user. Default: 300. To disable throttling set to 0.|
| `raw_blob_request_limit` | integer | no | Max number of requests per minute for each raw path. Default: 300. To disable throttling set to 0.|
+| `wiki_page_max_content_bytes` | integer | no | Max wiki page content size in **bytes**. Default: 52428800 Bytes (50MB).|
diff --git a/doc/user/project/merge_requests/img/file_by_file_v13_2.png b/doc/user/project/merge_requests/img/file_by_file_v13_2.png
new file mode 100644
index 00000000000..e3114ebabad
--- /dev/null
+++ b/doc/user/project/merge_requests/img/file_by_file_v13_2.png
Binary files differ
diff --git a/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md b/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
index a3ad41d8dd8..91ca48f85d5 100644
--- a/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
+++ b/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
@@ -64,6 +64,44 @@ list.
![Merge request diff file navigation](img/merge_request_diff_file_navigation.png)
+### File-by-file diff navigation
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222790) in GitLab 13.2.
+> - It's deployed behind a feature flag, enabled by default.
+> - It's recommended for production use.
+> - It's enabled on GitLab.com.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-file-by-file-diff-navigation-core-only).
+
+For larger merge requests it might sometimes be useful to review single files at a time. To enable,
+from your avatar on the top-right navbar, click **Settings**, and go to **Preferences** on the left
+sidebar. Scroll down to the **Behavior** section and select **Show one file at a time on merge request's Changes tab**.
+Click **Save changes** to apply.
+
+From there, when reviewing merge requests' **Changes** tab, you will see only one file at a time. You can then click the buttons **Prev** and **Next** to view the other files changed.
+
+![File-by-file diff navigation](img/file_by_file_v13_2.png)
+
+#### Enable or disable file-by-file diff navigation **(CORE ONLY)**
+
+File-by-file diff navigation is under development but ready for production use. It is
+deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can opt to disable it for your instance.
+
+To enable it:
+
+```ruby
+# Instance-wide
+Feature.enable(:view_diffs_file_by_file)
+```
+
+To disable it:
+
+```ruby
+# Instance-wide
+Feature.disable(:view_diffs_file_by_file>)
+```
+
### Merge requests commit navigation
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18140) in GitLab 13.0.
diff --git a/doc/user/project/repository/forking_workflow.md b/doc/user/project/repository/forking_workflow.md
index 75a84e36169..a17e788d3a4 100644
--- a/doc/user/project/repository/forking_workflow.md
+++ b/doc/user/project/repository/forking_workflow.md
@@ -26,7 +26,7 @@ Forking a project is, in most cases, a two-step process.
NOTE: **Note:**
The project path must be unique within the namespace.
- ![Choose namespace](img/forking_workflow_choose_namespace.png)
+ ![Choose namespace](img/forking_workflow_choose_namespace_v13_2.png)
The fork is created. The permissions you have in the namespace are the permissions you will have in the fork.
diff --git a/doc/user/project/repository/img/forking_workflow_choose_namespace.png b/doc/user/project/repository/img/forking_workflow_choose_namespace.png
deleted file mode 100644
index eb023ca85f2..00000000000
--- a/doc/user/project/repository/img/forking_workflow_choose_namespace.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/repository/img/forking_workflow_choose_namespace_v13_2.png b/doc/user/project/repository/img/forking_workflow_choose_namespace_v13_2.png
new file mode 100644
index 00000000000..6b3abeee5c3
--- /dev/null
+++ b/doc/user/project/repository/img/forking_workflow_choose_namespace_v13_2.png
Binary files differ
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
index c10d87a537b..968ff0fce89 100644
--- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -162,4 +162,4 @@ include:
- template: Security/Dependency-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
- template: Security/License-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml
- template: Security/SAST.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
- - template: Security/Secret-Detection.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml
+ - template: Security/Secret-Detection.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml
diff --git a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
index d7d927ac8ee..39e27ed14e3 100644
--- a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
@@ -23,7 +23,7 @@ dast_environment_deploy:
when: never
- if: $DAST_DISABLED || $DAST_DISABLED_FOR_DEFAULT_BRANCH
when: never
- - if: $DAST_WEBSITE # we don't need to create a review app if a URL is already given
+ - if: $DAST_WEBSITE # we don't need to create a review app if a URL is already given
when: never
- if: $CI_COMMIT_BRANCH &&
$CI_KUBERNETES_ACTIVE &&
@@ -46,7 +46,7 @@ stop_dast_environment:
when: never
- if: $DAST_DISABLED || $DAST_DISABLED_FOR_DEFAULT_BRANCH
when: never
- - if: $DAST_WEBSITE # we don't need to create a review app if a URL is already given
+ - if: $DAST_WEBSITE # we don't need to create a review app if a URL is already given
when: never
- if: $CI_COMMIT_BRANCH &&
$CI_KUBERNETES_ACTIVE &&
diff --git a/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
index 37f6cd216ca..4c4ae4f69fd 100644
--- a/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
@@ -144,8 +144,8 @@ gemnasium-python-dependency_scanning:
- '{Pipfile,*/Pipfile,*/*/Pipfile}'
- '{requires.txt,*/requires.txt,*/*/requires.txt}'
- '{setup.py,*/setup.py,*/*/setup.py}'
- # Support passing of $PIP_REQUIREMENTS_FILE
- # See https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuring-specific-analyzers-used-by-dependency-scanning
+ # Support passing of $PIP_REQUIREMENTS_FILE
+ # See https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuring-specific-analyzers-used-by-dependency-scanning
- if: $CI_COMMIT_BRANCH &&
$GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
$DS_DEFAULT_ANALYZERS =~ /gemnasium-python/ &&
diff --git a/lib/gitlab/usage_data/topology.rb b/lib/gitlab/usage_data/topology.rb
index 4bca2cb07e4..4ce1fdb7279 100644
--- a/lib/gitlab/usage_data/topology.rb
+++ b/lib/gitlab/usage_data/topology.rb
@@ -91,7 +91,7 @@ module Gitlab
def topology_node_cpus(client)
query_safely('gitlab_usage_ping:node_cpus:count', 'node_cpus', fallback: {}) do |query|
- aggregate_by_instance(client, one_week_average(query))
+ aggregate_by_instance(client, one_week_average(query, aggregation: :max))
end
end
@@ -228,8 +228,8 @@ module Gitlab
end
end
- def one_week_average(query)
- "avg_over_time (#{query}[1w])"
+ def one_week_average(query, aggregation: :avg)
+ "#{aggregation}_over_time (#{query}[1w])"
end
def aggregate_by_instance(client, query)
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 314bb6466c9..bfa1aa2060c 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -15713,9 +15713,6 @@ msgstr ""
msgid "No available groups to fork the project."
msgstr ""
-msgid "No available namespaces to fork the project."
-msgstr ""
-
msgid "No branches found"
msgstr ""
diff --git a/package.json b/package.json
index a8dfc5d49a8..2e92c00ce11 100644
--- a/package.json
+++ b/package.json
@@ -43,7 +43,7 @@
"@babel/preset-env": "^7.10.1",
"@gitlab/at.js": "1.5.5",
"@gitlab/svgs": "1.152.0",
- "@gitlab/ui": "17.33.0",
+ "@gitlab/ui": "17.34.0",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "^6.0.3-1",
"@sentry/browser": "^5.10.2",
diff --git a/qa/qa/page/project/fork/new.rb b/qa/qa/page/project/fork/new.rb
index 49c2205fd08..e2f2e9330dd 100644
--- a/qa/qa/page/project/fork/new.rb
+++ b/qa/qa/page/project/fork/new.rb
@@ -6,11 +6,11 @@ module QA
module Fork
class New < Page::Base
view 'app/views/projects/forks/_fork_button.html.haml' do
- element :fork_namespace_content
+ element :fork_namespace_button
end
def choose_namespace(namespace = Runtime::Namespace.path)
- click_element(:fork_namespace_content, name: namespace)
+ click_element(:fork_namespace_button, name: namespace)
end
end
end
diff --git a/spec/controllers/explore/projects_controller_spec.rb b/spec/controllers/explore/projects_controller_spec.rb
index fd86501ff5d..4ec890a528f 100644
--- a/spec/controllers/explore/projects_controller_spec.rb
+++ b/spec/controllers/explore/projects_controller_spec.rb
@@ -138,6 +138,33 @@ RSpec.describe Explore::ProjectsController do
end
end
+ shared_examples 'avoids N+1 queries' do
+ [:index, :trending, :starred].each do |endpoint|
+ describe "GET #{endpoint}" do
+ render_views
+
+ # some N+1 queries still exist
+ it 'avoids N+1 queries' do
+ projects = create_list(:project, 3, :repository, :public)
+ projects.each do |project|
+ pipeline = create(:ci_pipeline, :success, project: project, sha: project.commit.id)
+ create(:commit_status, :success, pipeline: pipeline, ref: pipeline.ref)
+ end
+
+ control = ActiveRecord::QueryRecorder.new { get endpoint }
+
+ new_projects = create_list(:project, 2, :repository, :public)
+ new_projects.each do |project|
+ pipeline = create(:ci_pipeline, :success, project: project, sha: project.commit.id)
+ create(:commit_status, :success, pipeline: pipeline, ref: pipeline.ref)
+ end
+
+ expect { get endpoint }.not_to exceed_query_limit(control).with_threshold(8)
+ end
+ end
+ end
+ end
+
context 'when user is signed in' do
let(:user) { create(:user) }
@@ -147,6 +174,7 @@ RSpec.describe Explore::ProjectsController do
include_examples 'explore projects'
include_examples "blocks high page numbers"
+ include_examples 'avoids N+1 queries'
context 'user preference sorting' do
let(:project) { create(:project) }
@@ -160,6 +188,7 @@ RSpec.describe Explore::ProjectsController do
context 'when user is not signed in' do
include_examples 'explore projects'
include_examples "blocks high page numbers"
+ include_examples 'avoids N+1 queries'
context 'user preference sorting' do
let(:project) { create(:project) }
diff --git a/spec/controllers/projects/forks_controller_spec.rb b/spec/controllers/projects/forks_controller_spec.rb
index 4c0fd7b8954..72c40fc5772 100644
--- a/spec/controllers/projects/forks_controller_spec.rb
+++ b/spec/controllers/projects/forks_controller_spec.rb
@@ -162,9 +162,25 @@ RSpec.describe Projects::ForksController do
end
context 'when user is signed in' do
- it 'responds with status 200' do
+ before do
sign_in(user)
+ end
+ context 'when JSON requested' do
+ it 'responds with available groups' do
+ get :new,
+ format: :json,
+ params: {
+ namespace_id: project.namespace,
+ project_id: project
+ }
+
+ expect(json_response['namespaces'].length).to eq(1)
+ expect(json_response['namespaces'].first['id']).to eq(group.id)
+ end
+ end
+
+ it 'responds with status 200' do
subject
expect(response).to have_gitlab_http_status(:ok)
diff --git a/spec/controllers/projects/tags_controller_spec.rb b/spec/controllers/projects/tags_controller_spec.rb
index 122d1b072d0..d213d003bed 100644
--- a/spec/controllers/projects/tags_controller_spec.rb
+++ b/spec/controllers/projects/tags_controller_spec.rb
@@ -120,10 +120,14 @@ RSpec.describe Projects::TagsController do
request
- release = project.releases.find_by_tag!('1.0')
+ aggregate_failures do
+ expect(response).to have_gitlab_http_status(:found)
- expect(release).to be_present
- expect(release.description).to eq(release_description)
+ release = project.releases.find_by_tag('1.0')
+
+ expect(release).to be_present
+ expect(release&.description).to eq(release_description)
+ end
end
end
end
diff --git a/spec/features/projects/fork_spec.rb b/spec/features/projects/fork_spec.rb
index f0ed4013230..1e84d1552a1 100644
--- a/spec/features/projects/fork_spec.rb
+++ b/spec/features/projects/fork_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Project fork' do
it 'allows user to fork project' do
visit project_path(project)
- expect(page).not_to have_css('a.disabled', text: 'Fork')
+ expect(page).not_to have_css('a.disabled', text: 'Select')
end
it 'disables fork button when user has exceeded project limit' do
@@ -40,7 +40,7 @@ RSpec.describe 'Project fork' do
visit project_path(project)
expect(page).to have_css('a', text: 'Fork')
- expect(page).not_to have_css('a.disabled', text: 'Fork')
+ expect(page).not_to have_css('a.disabled', text: 'Select')
end
it 'renders new project fork page' do
@@ -116,7 +116,7 @@ RSpec.describe 'Project fork' do
click_link 'Fork'
page.within '.fork-thumbnail-container' do
- click_link user.name
+ click_link 'Select'
end
expect(page).to have_content 'Forked from'
@@ -156,7 +156,7 @@ RSpec.describe 'Project fork' do
click_link 'Fork'
page.within '.fork-thumbnail-container' do
- click_link user.name
+ click_link 'Select'
end
visit project_forks_path(project)
@@ -193,7 +193,7 @@ RSpec.describe 'Project fork' do
click_link 'Fork'
page.within '.fork-thumbnail-container' do
- click_link user.name
+ click_link 'Select'
end
visit project_forks_path(project)
@@ -218,7 +218,7 @@ RSpec.describe 'Project fork' do
click_link 'Fork'
page.within '.fork-thumbnail-container' do
- click_link user.name
+ click_link 'Select'
end
expect(page).to have_content "Name has already been taken"
@@ -232,39 +232,43 @@ RSpec.describe 'Project fork' do
group.add_maintainer(user)
end
- it 'allows user to fork project to group or to user namespace' do
+ it 'allows user to fork project to group or to user namespace', :js do
visit project_path(project)
+ wait_for_requests
expect(page).not_to have_css('a.disabled', text: 'Fork')
click_link 'Fork'
- expect(page).to have_css('.fork-thumbnail', count: 2)
+ expect(page).to have_css('.fork-thumbnail')
+ expect(page).to have_css('.group-row')
expect(page).not_to have_css('.fork-thumbnail.disabled')
end
- it 'allows user to fork project to group and not user when exceeded project limit' do
+ it 'allows user to fork project to group and not user when exceeded project limit', :js do
user.projects_limit = 0
user.save!
visit project_path(project)
+ wait_for_requests
expect(page).not_to have_css('a.disabled', text: 'Fork')
click_link 'Fork'
- expect(page).to have_css('.fork-thumbnail', count: 2)
expect(page).to have_css('.fork-thumbnail.disabled')
+ expect(page).to have_css('.group-row')
end
- it 'links to the fork if the project was already forked within that namespace', :sidekiq_might_not_need_inline do
+ it 'links to the fork if the project was already forked within that namespace', :sidekiq_might_not_need_inline, :js do
forked_project = fork_project(project, user, namespace: group, repository: true)
visit new_project_fork_path(project)
+ wait_for_requests
- expect(page).to have_css('div.forked', text: group.full_name)
+ expect(page).to have_css('.group-row a.btn', text: 'Go to fork')
- click_link group.full_name
+ click_link 'Go to fork'
expect(current_path).to eq(project_path(forked_project))
end
diff --git a/spec/frontend/incidents_settings/components/incidents_settings_tabs_spec.js b/spec/frontend/incidents_settings/components/incidents_settings_tabs_spec.js
index 47e2aecc108..c56b9ed2a69 100644
--- a/spec/frontend/incidents_settings/components/incidents_settings_tabs_spec.js
+++ b/spec/frontend/incidents_settings/components/incidents_settings_tabs_spec.js
@@ -6,9 +6,7 @@ describe('IncidentsSettingTabs', () => {
let wrapper;
beforeEach(() => {
- wrapper = shallowMount(IncidentsSettingTabs, {
- provide: { glFeatures: { pagerdutyWebhook: true } },
- });
+ wrapper = shallowMount(IncidentsSettingTabs);
});
afterEach(() => {
diff --git a/spec/frontend/monitoring/components/refresh_button_spec.js b/spec/frontend/monitoring/components/refresh_button_spec.js
index 29615638453..730d2b82568 100644
--- a/spec/frontend/monitoring/components/refresh_button_spec.js
+++ b/spec/frontend/monitoring/components/refresh_button_spec.js
@@ -10,8 +10,8 @@ describe('RefreshButton', () => {
let dispatch;
let documentHidden;
- const createWrapper = () => {
- wrapper = shallowMount(RefreshButton, { store });
+ const createWrapper = (options = {}) => {
+ wrapper = shallowMount(RefreshButton, { store, ...options });
};
const findRefreshBtn = () => wrapper.find(GlButton);
@@ -57,6 +57,20 @@ describe('RefreshButton', () => {
expect(findDropdown().props('text')).toBe('Off');
});
+ describe('when feature flag disable_metric_dashboard_refresh_rate is on', () => {
+ beforeEach(() => {
+ createWrapper({
+ provide: {
+ glFeatures: { disableMetricDashboardRefreshRate: true },
+ },
+ });
+ });
+
+ it('refresh rate is not available', () => {
+ expect(findDropdown().exists()).toBe(false);
+ });
+ });
+
describe('refresh rate options', () => {
it('presents multiple options', () => {
expect(findOptions().length).toBeGreaterThan(1);
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js
index 0e8610a22f5..c11b0234e91 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js
@@ -47,4 +47,24 @@ describe('HTMLToMarkdownRenderer', () => {
expect(baseRenderer.convert).toHaveBeenCalledWith(NODE, list);
});
});
+
+ describe('UL LI visitor', () => {
+ it.each`
+ listItem | unorderedListBulletChar | result | bulletChar
+ ${'* list item'} | ${undefined} | ${'- list item'} | ${'default'}
+ ${' - list item'} | ${'*'} | ${' * list item'} | ${'*'}
+ ${' * list item'} | ${'-'} | ${' - list item'} | ${'-'}
+ `(
+ 'uses $bulletChar bullet char in unordered list items when $unorderedListBulletChar is set in config',
+ ({ listItem, unorderedListBulletChar, result }) => {
+ htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer, {
+ unorderedListBulletChar,
+ });
+ baseRenderer.convert.mockReturnValueOnce(listItem);
+
+ expect(htmlToMarkdownRenderer['UL LI'](NODE, listItem)).toBe(result);
+ expect(baseRenderer.convert).toHaveBeenCalledWith(NODE, listItem);
+ },
+ );
+ });
});
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index f618e13ca26..4f5a1f0dcc2 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -72,6 +72,7 @@ RSpec.describe ApplicationSetting do
it { is_expected.not_to allow_value(nil).for(:push_event_activities_limit) }
it { is_expected.to validate_numericality_of(:snippet_size_limit).only_integer.is_greater_than(0) }
+ it { is_expected.to validate_numericality_of(:wiki_page_max_content_bytes).only_integer.is_greater_than(0) }
it { is_expected.to validate_presence_of(:max_artifacts_size) }
it { is_expected.to validate_numericality_of(:max_artifacts_size).only_integer.is_greater_than(0) }
it { is_expected.to validate_presence_of(:max_pages_size) }
diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb
index 716e7dc786e..fea15ea00c8 100644
--- a/spec/models/release_spec.rb
+++ b/spec/models/release_spec.rb
@@ -73,6 +73,22 @@ RSpec.describe Release do
end
end
+ describe '.create' do
+ it "fills released_at using created_at if it's not set" do
+ release = described_class.create(project: project, author: user)
+
+ expect(release.released_at).to eq(release.created_at)
+ end
+
+ it "does not change released_at if it's set explicitly" do
+ released_at = Time.zone.parse('2018-10-20T18:00:00Z')
+
+ release = described_class.create(project: project, author: user, released_at: released_at)
+
+ expect(release.released_at).to eq(released_at)
+ end
+ end
+
describe '#sources' do
subject { release.sources }
diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb
index a2ca6441f28..1d10a3a3e6a 100644
--- a/spec/models/wiki_page_spec.rb
+++ b/spec/models/wiki_page_spec.rb
@@ -267,6 +267,53 @@ RSpec.describe WikiPage do
expect(subject.errors.keys).to contain_exactly(:content)
end
+ describe 'content size validation' do
+ let(:limit) { 10 }
+
+ before do
+ stub_application_setting(wiki_page_max_content_bytes: limit)
+ end
+
+ it 'accepts content below the limit' do
+ subject.attributes[:content] = 'a' * 10
+
+ expect(subject).to be_valid
+ end
+
+ it 'rejects content exceeding the limit' do
+ subject.attributes[:content] = 'a' * 11
+
+ expect(subject).not_to be_valid
+ expect(subject.errors.messages).to eq(
+ content: ['is too long (11 Bytes). The maximum size is 10 Bytes.']
+ )
+ end
+
+ it 'counts content size in bytes rather than characters' do
+ subject.attributes[:content] = '💩💩💩'
+
+ expect(subject).not_to be_valid
+ expect(subject.errors.messages).to eq(
+ content: ['is too long (12 Bytes). The maximum size is 10 Bytes.']
+ )
+ end
+
+ context 'with an existing page exceeding the limit' do
+ let(:limit) { existing_page.content.bytesize - 1 }
+
+ it 'accepts content when it has not changed' do
+ expect(existing_page).to be_valid
+ end
+
+ it 'rejects content when it has changed' do
+ existing_page.attributes[:content] = 'a' * (limit + 1)
+
+ expect(existing_page).not_to be_valid
+ expect(existing_page.errors.keys).to contain_exactly(:content)
+ end
+ end
+ end
+
describe '#validate_path_limits' do
let(:max_title) { Gitlab::WikiPages::MAX_TITLE_BYTES }
let(:max_directory) { Gitlab::WikiPages::MAX_DIRECTORY_BYTES }
@@ -702,6 +749,50 @@ RSpec.describe WikiPage do
end
end
+ describe '#content_changed?' do
+ context 'with a new page' do
+ subject { new_page }
+
+ it 'returns false if content is nil' do
+ subject.attributes[:content] = nil
+
+ expect(subject.content_changed?).to be(false)
+ end
+
+ it 'returns true if content is set' do
+ subject.attributes[:content] = 'new'
+
+ expect(subject.content_changed?).to be(true)
+ end
+
+ it 'returns true if content is blank' do
+ subject.attributes[:content] = ''
+
+ expect(subject.content_changed?).to be(true)
+ end
+ end
+
+ context 'with an existing page' do
+ subject { existing_page }
+
+ it 'returns false' do
+ expect(subject.content_changed?).to be(false)
+ end
+
+ it 'returns false if content is set to the same value' do
+ subject.attributes[:content] = 'test content'
+
+ expect(subject.content_changed?).to be(false)
+ end
+
+ it 'returns true if content is changed' do
+ subject.attributes[:content] = 'new'
+
+ expect(subject.content_changed?).to be(true)
+ end
+ end
+ end
+
describe '#path' do
it 'returns the path when persisted' do
expect(existing_page.path).to eq('test-page.md')
diff --git a/spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb b/spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb
index cf43ed2411d..73ad0532e07 100644
--- a/spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb
+++ b/spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb
@@ -12,84 +12,63 @@ RSpec.describe IncidentManagement::PagerDuty::CreateIncidentIssueService do
subject(:execute) { described_class.new(project, incident_payload).execute }
describe '#execute' do
- context 'when pagerduty_webhook feature enabled' do
- before do
- stub_feature_flags(pagerduty_webhook: project)
- end
+ context 'when PagerDuty webhook setting is active' do
+ let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: true) }
- context 'when PagerDuty webhook setting is active' do
- let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: true) }
-
- context 'when issue can be created' do
- it 'creates a new issue' do
- expect { execute }.to change(Issue, :count).by(1)
- end
-
- it 'responds with success' do
- response = execute
-
- expect(response).to be_success
- expect(response.payload[:issue]).to be_kind_of(Issue)
- end
-
- it 'the issue author is Alert bot' do
- expect(execute.payload[:issue].author).to eq(User.alert_bot)
- end
-
- it 'issue has a correct title' do
- expect(execute.payload[:issue].title).to eq(incident_payload['title'])
- end
-
- it 'issue has a correct description' do
- markdown_line_break = ' '
-
- expect(execute.payload[:issue].description).to eq(
- <<~MARKDOWN.chomp
- **Incident:** [My new incident](https://webdemo.pagerduty.com/incidents/PRORDTY)#{markdown_line_break}
- **Incident number:** 33#{markdown_line_break}
- **Urgency:** high#{markdown_line_break}
- **Status:** triggered#{markdown_line_break}
- **Incident key:** #{markdown_line_break}
- **Created at:** 26 September 2017, 3:14PM (UTC)#{markdown_line_break}
- **Assignees:** [Laura Haley](https://webdemo.pagerduty.com/users/P553OPV)#{markdown_line_break}
- **Impacted services:** [Production XDB Cluster](https://webdemo.pagerduty.com/services/PN49J75)
- MARKDOWN
- )
- end
+ context 'when issue can be created' do
+ it 'creates a new issue' do
+ expect { execute }.to change(Issue, :count).by(1)
end
- context 'when the payload does not contain a title' do
- let(:incident_payload) { {} }
+ it 'responds with success' do
+ response = execute
+
+ expect(response).to be_success
+ expect(response.payload[:issue]).to be_kind_of(Issue)
+ end
- it 'does not create a GitLab issue' do
- expect { execute }.not_to change(Issue, :count)
- end
+ it 'the issue author is Alert bot' do
+ expect(execute.payload[:issue].author).to eq(User.alert_bot)
+ end
- it 'responds with error' do
- expect(execute).to be_error
- expect(execute.message).to eq("Title can't be blank")
- end
+ it 'issue has a correct title' do
+ expect(execute.payload[:issue].title).to eq(incident_payload['title'])
+ end
+
+ it 'issue has a correct description' do
+ markdown_line_break = ' '
+
+ expect(execute.payload[:issue].description).to eq(
+ <<~MARKDOWN.chomp
+ **Incident:** [My new incident](https://webdemo.pagerduty.com/incidents/PRORDTY)#{markdown_line_break}
+ **Incident number:** 33#{markdown_line_break}
+ **Urgency:** high#{markdown_line_break}
+ **Status:** triggered#{markdown_line_break}
+ **Incident key:** #{markdown_line_break}
+ **Created at:** 26 September 2017, 3:14PM (UTC)#{markdown_line_break}
+ **Assignees:** [Laura Haley](https://webdemo.pagerduty.com/users/P553OPV)#{markdown_line_break}
+ **Impacted services:** [Production XDB Cluster](https://webdemo.pagerduty.com/services/PN49J75)
+ MARKDOWN
+ )
end
end
- context 'when PagerDuty webhook setting is not active' do
- let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: false) }
+ context 'when the payload does not contain a title' do
+ let(:incident_payload) { {} }
it 'does not create a GitLab issue' do
expect { execute }.not_to change(Issue, :count)
end
- it 'responds with forbidden' do
+ it 'responds with error' do
expect(execute).to be_error
- expect(execute.http_status).to eq(:forbidden)
+ expect(execute.message).to eq("Title can't be blank")
end
end
end
- context 'when pagerduty_webhook feature disabled' do
- before do
- stub_feature_flags(pagerduty_webhook: false)
- end
+ context 'when PagerDuty webhook setting is not active' do
+ let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: false) }
it 'does not create a GitLab issue' do
expect { execute }.not_to change(Issue, :count)
diff --git a/spec/services/incident_management/pager_duty/process_webhook_service_spec.rb b/spec/services/incident_management/pager_duty/process_webhook_service_spec.rb
index 11ce8388427..4c8aebe5fe2 100644
--- a/spec/services/incident_management/pager_duty/process_webhook_service_spec.rb
+++ b/spec/services/incident_management/pager_duty/process_webhook_service_spec.rb
@@ -19,92 +19,68 @@ RSpec.describe IncidentManagement::PagerDuty::ProcessWebhookService do
subject(:execute) { described_class.new(project, nil, webhook_payload).execute(token) }
- context 'when pagerduty_webhook feature is enabled' do
- before do
- stub_feature_flags(pagerduty_webhook: project)
- end
-
- context 'when PagerDuty webhook setting is active' do
- let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: true) }
-
- context 'when token is valid' do
- let(:token) { incident_management_setting.pagerduty_token }
+ context 'when PagerDuty webhook setting is active' do
+ let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: true) }
- context 'when webhook payload has acceptable size' do
- it 'responds with Accepted' do
- result = execute
+ context 'when token is valid' do
+ let(:token) { incident_management_setting.pagerduty_token }
- expect(result).to be_success
- expect(result.http_status).to eq(:accepted)
- end
-
- it 'processes issues' do
- incident_payload = ::PagerDuty::WebhookPayloadParser.call(webhook_payload).first['incident']
-
- expect(::IncidentManagement::PagerDuty::ProcessIncidentWorker)
- .to receive(:perform_async)
- .with(project.id, incident_payload)
- .once
+ context 'when webhook payload has acceptable size' do
+ it 'responds with Accepted' do
+ result = execute
- execute
- end
+ expect(result).to be_success
+ expect(result.http_status).to eq(:accepted)
end
- context 'when webhook payload is too big' do
- let(:deep_size) { instance_double(Gitlab::Utils::DeepSize, valid?: false) }
-
- before do
- allow(Gitlab::Utils::DeepSize)
- .to receive(:new)
- .with(webhook_payload, max_size: described_class::PAGER_DUTY_PAYLOAD_SIZE_LIMIT)
- .and_return(deep_size)
- end
+ it 'processes issues' do
+ incident_payload = ::PagerDuty::WebhookPayloadParser.call(webhook_payload).first['incident']
- it 'responds with Bad Request' do
- result = execute
+ expect(::IncidentManagement::PagerDuty::ProcessIncidentWorker)
+ .to receive(:perform_async)
+ .with(project.id, incident_payload)
+ .once
- expect(result).to be_error
- expect(result.http_status).to eq(:bad_request)
- end
-
- it_behaves_like 'does not process incidents'
+ execute
end
+ end
- context 'when webhook payload is blank' do
- let(:webhook_payload) { nil }
+ context 'when webhook payload is too big' do
+ let(:deep_size) { instance_double(Gitlab::Utils::DeepSize, valid?: false) }
- it 'responds with Accepted' do
- result = execute
+ before do
+ allow(Gitlab::Utils::DeepSize)
+ .to receive(:new)
+ .with(webhook_payload, max_size: described_class::PAGER_DUTY_PAYLOAD_SIZE_LIMIT)
+ .and_return(deep_size)
+ end
- expect(result).to be_success
- expect(result.http_status).to eq(:accepted)
- end
+ it 'responds with Bad Request' do
+ result = execute
- it_behaves_like 'does not process incidents'
+ expect(result).to be_error
+ expect(result.http_status).to eq(:bad_request)
end
+
+ it_behaves_like 'does not process incidents'
end
- context 'when token is invalid' do
- let(:token) { 'invalid-token' }
+ context 'when webhook payload is blank' do
+ let(:webhook_payload) { nil }
- it 'responds with Unauthorized' do
+ it 'responds with Accepted' do
result = execute
- expect(result).to be_error
- expect(result.http_status).to eq(:unauthorized)
+ expect(result).to be_success
+ expect(result.http_status).to eq(:accepted)
end
it_behaves_like 'does not process incidents'
end
end
- context 'when both tokens are nil' do
- let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: false) }
- let(:token) { nil }
-
- before do
- incident_management_setting.update_column(:pagerduty_active, true)
- end
+ context 'when token is invalid' do
+ let(:token) { 'invalid-token' }
it 'responds with Unauthorized' do
result = execute
@@ -115,25 +91,28 @@ RSpec.describe IncidentManagement::PagerDuty::ProcessWebhookService do
it_behaves_like 'does not process incidents'
end
+ end
- context 'when PagerDuty webhook setting is not active' do
- let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: false) }
+ context 'when both tokens are nil' do
+ let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: false) }
+ let(:token) { nil }
- it 'responds with Forbidden' do
- result = execute
+ before do
+ incident_management_setting.update_column(:pagerduty_active, true)
+ end
- expect(result).to be_error
- expect(result.http_status).to eq(:forbidden)
- end
+ it 'responds with Unauthorized' do
+ result = execute
- it_behaves_like 'does not process incidents'
+ expect(result).to be_error
+ expect(result.http_status).to eq(:unauthorized)
end
+
+ it_behaves_like 'does not process incidents'
end
- context 'when pagerduty_webhook feature is disabled' do
- before do
- stub_feature_flags(pagerduty_webhook: false)
- end
+ context 'when PagerDuty webhook setting is not active' do
+ let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: false) }
it 'responds with Forbidden' do
result = execute
diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb
index c49aa42b147..1e4038fab79 100644
--- a/spec/services/projects/fork_service_spec.rb
+++ b/spec/services/projects/fork_service_spec.rb
@@ -439,37 +439,71 @@ RSpec.describe Projects::ForkService do
end
describe '#valid_fork_target?' do
- subject { described_class.new(project, user, params).valid_fork_target? }
-
let(:project) { Project.new }
let(:params) { {} }
- context 'when current user is an admin' do
- let(:user) { build(:user, :admin) }
+ context 'when target is not passed' do
+ subject { described_class.new(project, user, params).valid_fork_target? }
- it { is_expected.to be_truthy }
- end
+ context 'when current user is an admin' do
+ let(:user) { build(:user, :admin) }
- context 'when current_user is not an admin' do
- let(:user) { create(:user) }
+ it { is_expected.to be_truthy }
+ end
- let(:finder_mock) { instance_double('ForkTargetsFinder', execute: [user.namespace]) }
- let(:project) { create(:project) }
+ context 'when current_user is not an admin' do
+ let(:user) { create(:user) }
- before do
- allow(ForkTargetsFinder).to receive(:new).with(project, user).and_return(finder_mock)
+ let(:finder_mock) { instance_double('ForkTargetsFinder', execute: [user.namespace]) }
+ let(:project) { create(:project) }
+
+ before do
+ allow(ForkTargetsFinder).to receive(:new).with(project, user).and_return(finder_mock)
+ end
+
+ context 'when target namespace is in valid fork targets' do
+ let(:params) { { namespace: user.namespace } }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when target namespace is not in valid fork targets' do
+ let(:params) { { namespace: create(:group) } }
+
+ it { is_expected.to be_falsey }
+ end
end
+ end
+
+ context 'when target is passed' do
+ let(:target) { create(:group) }
- context 'when target namespace is in valid fork targets' do
- let(:params) { { namespace: user.namespace } }
+ subject { described_class.new(project, user, params).valid_fork_target?(target) }
+
+ context 'when current user is an admin' do
+ let(:user) { build(:user, :admin) }
it { is_expected.to be_truthy }
end
- context 'when target namespace is not in valid fork targets' do
- let(:params) { { namespace: create(:group) } }
+ context 'when current user is not an admin' do
+ let(:user) { create(:user) }
+
+ before do
+ allow(ForkTargetsFinder).to receive(:new).with(project, user).and_return(finder_mock)
+ end
+
+ context 'when target namespace is in valid fork targets' do
+ let(:finder_mock) { instance_double('ForkTargetsFinder', execute: [target]) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when target namespace is not in valid fork targets' do
+ let(:finder_mock) { instance_double('ForkTargetsFinder', execute: [create(:group)]) }
- it { is_expected.to be_falsey }
+ it { is_expected.to be_falsey }
+ end
end
end
end
diff --git a/yarn.lock b/yarn.lock
index 797107e8272..d4be37c3349 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -848,10 +848,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.152.0.tgz#663c9a5f073f59b66f4241ef2d3fea2205846905"
integrity sha512-daZHOBVAwjsU6n60IycanoO/JymfQ36vrr46OUdWjHdp0ATYrgh+01LcxiSNLdlyndIRqHWGtwmuilokM9q6Vg==
-"@gitlab/ui@17.33.0":
- version "17.33.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-17.33.0.tgz#d0b3e8bf268fe9a28e97a6aa71b5a02059078206"
- integrity sha512-WszO9zRhO5EkbLrpujPMDgrHIymkSGXRRwg32TzqASSrl4WymdgSpGYVXdTu95c1n3n7pngkjOEdh/90aM89FQ==
+"@gitlab/ui@17.34.0":
+ version "17.34.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-17.34.0.tgz#4f3708579d6822280c26e27b6055e29336be4871"
+ integrity sha512-g8mhdB8lOn7lFeWvWkEu5xqV/A0RZDfAMEU2aylLeInTCIrn2V638y80U4Kb2Suu78ji/rYgtjZRSmy8ZDvAQA==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"