summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md49
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock17
-rw-r--r--PROCESS.md27
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_table.vue2
-rw-r--r--app/assets/javascripts/environments/components/container.vue2
-rw-r--r--app/assets/javascripts/environments/mixins/environments_mixin.js2
-rw-r--r--app/assets/javascripts/ide/components/ide.vue2
-rw-r--r--app/assets/javascripts/ide/components/ide_status_bar.vue16
-rw-r--r--app/assets/javascripts/ide/components/ide_status_list.vue23
-rw-r--r--app/assets/javascripts/lib/utils/invalid_url.js6
-rw-r--r--app/assets/javascripts/monitoring/components/charts/area.vue5
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue39
-rw-r--r--app/assets/javascripts/monitoring/monitoring_bundle.js5
-rw-r--r--app/assets/javascripts/monitoring/stores/actions.js90
-rw-r--r--app/assets/javascripts/monitoring/stores/mutation_types.js3
-rw-r--r--app/assets/javascripts/monitoring/stores/mutations.js53
-rw-r--r--app/assets/javascripts/monitoring/stores/state.js5
-rw-r--r--app/assets/javascripts/monitoring/stores/utils.js16
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines.vue2
-rw-r--r--app/assets/javascripts/registry/components/table_registry.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue (renamed from app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue)16
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue47
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/constants.js10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mixins/auto_merge.js15
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue24
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js22
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/commit.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/pagination/table_pagination.vue (renamed from app/assets/javascripts/vue_shared/components/table_pagination.vue)0
-rw-r--r--app/assets/stylesheets/page_bundles/ide.scss15
-rw-r--r--app/controllers/admin/application_settings_controller.rb6
-rw-r--r--app/controllers/projects/merge_requests_controller.rb12
-rw-r--r--app/graphql/types/tree/blob_type.rb2
-rw-r--r--app/helpers/environments_helper.rb1
-rw-r--r--app/models/notification_recipient.rb5
-rw-r--r--app/models/project.rb2
-rw-r--r--app/presenters/ci/build_runner_presenter.rb2
-rw-r--r--app/services/auto_merge/base_service.rb8
-rw-r--r--app/services/auto_merge_service.rb6
-rw-r--r--app/services/projects/fork_service.rb6
-rw-r--r--app/views/admin/application_settings/_visibility_and_access.html.haml1
-rw-r--r--app/views/projects/branches/_branch.html.haml2
-rw-r--r--changelogs/archive.md36
-rw-r--r--changelogs/unreleased/5615-non-admins-only-archieve-ce.yml5
-rw-r--r--changelogs/unreleased/58433-email-notifications-do-not-work-properly-issue-due-date.yml5
-rw-r--r--changelogs/unreleased/58984-doc-missing-milestones-and-labels-links.yml5
-rw-r--r--changelogs/unreleased/59651-remove-unnecessary-decimal-places-on-chart-axes.yml5
-rw-r--r--changelogs/unreleased/62300-target-area-for-dropdown-list-items-is-too-small-on-metrics-dashboard.yml5
-rw-r--r--changelogs/unreleased/62788-clean-up-pagination.yml5
-rw-r--r--changelogs/unreleased/9186-implement-atmtwps-state-to-mr-widget.yml5
-rw-r--r--changelogs/unreleased/expose-project-git-depth-via-api.yml5
-rw-r--r--changelogs/unreleased/fix-diverged-branch-locals.yml5
-rw-r--r--changelogs/unreleased/patch-65.yml5
-rw-r--r--changelogs/unreleased/upgrade-pages-to-v1-6-1.yml5
-rw-r--r--config/initializers/rack_timeout.rb2
-rw-r--r--db/migrate/20190605104727_add_default_project_deletion_protection_to_application_settings.rb20
-rw-r--r--db/schema.rb1
-rw-r--r--doc/administration/repository_storage_types.md5
-rw-r--r--doc/api/projects.md8
-rw-r--r--doc/ci/docker/using_docker_build.md2
-rw-r--r--doc/ci/docker/using_docker_images.md95
-rw-r--r--doc/ci/examples/README.md6
-rw-r--r--doc/ci/metrics_reports.md5
-rw-r--r--doc/development/git_object_deduplication.md109
-rw-r--r--doc/development/gitaly.md2
-rw-r--r--doc/development/testing_guide/best_practices.md2
-rw-r--r--doc/development/testing_guide/end_to_end/quick_start_guide.md2
-rw-r--r--doc/gitlab-basics/README.md1
-rw-r--r--doc/integration/elasticsearch.md2
-rw-r--r--doc/migrate_ci_to_ce/README.md19
-rw-r--r--doc/policy/maintenance.md25
-rw-r--r--doc/public_access/public_access.md53
-rw-r--r--doc/push_rules/push_rules.md29
-rw-r--r--doc/ssh/README.md14
-rw-r--r--doc/subscriptions/index.md19
-rw-r--r--doc/system_hooks/system_hooks.md24
-rw-r--r--doc/tools/email.md34
-rw-r--r--doc/topics/autodevops/index.md2
-rw-r--r--doc/university/README.md1
-rw-r--r--doc/university/glossary/README.md707
-rw-r--r--doc/user/application_security/dependency_scanning/index.md153
-rw-r--r--doc/user/application_security/sast/index.md114
-rw-r--r--doc/user/group/index.md12
-rw-r--r--doc/user/group/insights/index.md6
-rw-r--r--doc/user/instance_statistics/convdev.md2
-rw-r--r--doc/user/project/cycle_analytics.md18
-rw-r--r--doc/user/project/import/github.md2
-rw-r--r--doc/user/project/index.md1
-rw-r--r--doc/user/project/insights/index.md6
-rw-r--r--doc/user/project/settings/index.md6
-rw-r--r--doc/workflow/gitlab_flow.md2
-rw-r--r--lib/api/entities.rb2
-rw-r--r--lib/api/helpers/projects_helpers.rb1
-rw-r--r--lib/gitlab/ci/templates/Serverless.gitlab-ci.yml2
-rw-r--r--lib/gitlab/cluster/rack_timeout_observer.rb51
-rw-r--r--lib/gitlab/graphql/loaders/batch_lfs_oid_loader.rb (renamed from lib/gitlab/graphql/loaders/batch_commit_loader.rb)2
-rw-r--r--lib/gitlab/rack_timeout_observer.rb46
-rw-r--r--locale/gitlab.pot6
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb3
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb26
-rw-r--r--spec/controllers/projects/settings/ci_cd_controller_spec.rb2
-rw-r--r--spec/features/commits_spec.rb6
-rw-r--r--spec/features/ics/dashboard_issues_spec.rb2
-rw-r--r--spec/features/ics/group_issues_spec.rb2
-rw-r--r--spec/features/ics/project_issues_spec.rb2
-rw-r--r--spec/features/merge_request/user_accepts_merge_request_spec.rb3
-rw-r--r--spec/features/merge_request/user_creates_image_diff_notes_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_diff_spec.rb3
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb4
-rw-r--r--spec/features/merge_request/user_suggests_changes_on_diff_spec.rb4
-rw-r--r--spec/features/projects/commits/user_browses_commits_spec.rb2
-rw-r--r--spec/features/projects/features_visibility_spec.rb3
-rw-r--r--spec/features/projects/files/undo_template_spec.rb2
-rw-r--r--spec/features/projects/files/user_creates_files_spec.rb1
-rw-r--r--spec/features/projects/labels/user_removes_labels_spec.rb2
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb2
-rw-r--r--spec/features/projects/settings/integration_settings_spec.rb2
-rw-r--r--spec/features/projects/tree/upload_file_spec.rb2
-rw-r--r--spec/features/search/user_searches_for_commits_spec.rb2
-rw-r--r--spec/features/tags/master_creates_tag_spec.rb2
-rw-r--r--spec/frontend/ide/components/ide_status_list_spec.js91
-rw-r--r--spec/javascripts/monitoring/charts/area_spec.js14
-rw-r--r--spec/javascripts/monitoring/dashboard_spec.js4
-rw-r--r--spec/javascripts/monitoring/mock_data.js65
-rw-r--r--spec/javascripts/monitoring/store/actions_spec.js166
-rw-r--r--spec/javascripts/monitoring/store/mutations_spec.js77
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js (renamed from spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js)62
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js136
-rw-r--r--spec/javascripts/vue_mr_widget/mock_data.js7
-rw-r--r--spec/javascripts/vue_mr_widget/mr_widget_options_spec.js54
-rw-r--r--spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js42
-rw-r--r--spec/javascripts/vue_shared/components/table_pagination_spec.js2
-rw-r--r--spec/lib/gitlab/cluster/rack_timeout_observer_spec.rb (renamed from spec/lib/gitlab/rack_timeout_observer_spec.rb)25
-rw-r--r--spec/lib/gitlab/graphql/loaders/batch_lfs_oid_loader_spec.rb (renamed from spec/lib/gitlab/graphql/loaders/batch_commit_loader_spec.rb)2
-rw-r--r--spec/models/notification_recipient_spec.rb233
-rw-r--r--spec/presenters/ci/build_runner_presenter_spec.rb2
-rw-r--r--spec/requests/api/projects_spec.rb2
-rw-r--r--spec/requests/api/runner_spec.rb6
-rw-r--r--spec/services/auto_merge/base_service_spec.rb24
-rw-r--r--spec/services/auto_merge_service_spec.rb28
-rw-r--r--spec/services/projects/fork_service_spec.rb8
-rw-r--r--spec/support/capybara.rb2
-rw-r--r--spec/support/features/discussion_comments_shared_example.rb2
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/shrug_quick_action_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/tableflip_quick_action_shared_examples.rb2
-rw-r--r--spec/views/notify/pipeline_failed_email.html.haml_spec.rb4
-rw-r--r--spec/views/notify/pipeline_failed_email.text.erb_spec.rb2
-rw-r--r--spec/views/notify/pipeline_success_email.html.haml_spec.rb4
-rw-r--r--spec/views/profiles/show.html.haml_spec.rb4
152 files changed, 2142 insertions, 1311 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8498658b39c..623e5d0acb9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -660,7 +660,7 @@ entry.
- Forbid creating discussions for users with restricted access.
- Fix leaking private repository information in API.
- Fixed ability to see private groups by users not belonging to given group.
-- Prevent releases links API to leak tag existance.
+- Prevent releases links API to leak tag existence.
- Display the correct number of MRs a user has access to.
- Block local URLs for Kubernetes integration.
- Fix arbitrary file read via diffs during import.
@@ -1019,7 +1019,7 @@ entry.
- Display SAML failure messages instead of expecting CSRF token. !24509
- Adjust vertical alignment for project visibility icons. !24511 (Martin Hobert)
- Load initUserInternalRegexPlaceholder only when required. !24522
-- Hashed Storage: `AfterRenameService` was receiving the wrong `old_path` under some circunstances. !24526
+- Hashed Storage: `AfterRenameService` was receiving the wrong `old_path` under some circumstances. !24526
- Resolve Runners IPv6 address overlaps other values. !24531
- Fix 404s with snippet uploads in object storage. !24550
- Fixed oversized custom project notification selector dropdown. !24557
@@ -1058,7 +1058,7 @@ entry.
- Update CI YAML param table with include.
- Return bottom border on MR Tabs.
- Fixes z-index and margins of archived alert in job page.
-- Fixes archived sticky top bar without perfomance bar.
+- Fixes archived sticky top bar without performance bar.
- Fixed rebase button not showing in merge request widget.
- Fixed double tooltips on note awards buttons.
- Allow suggestions to be copied and pasted as GFM.
@@ -1491,7 +1491,7 @@ entry.
- Fix deprecation: Using positional arguments in integration tests. !24009 (Jasper Maes)
- UI improvements for redesigned project lists. !24011
- Update cert-manager chart from v0.5.0 to v0.5.2. !24025 (Takuya Noguchi)
-- Hide spinner on empty activites list on user profile overview. !24063
+- Hide spinner on empty activities list on user profile overview. !24063
- Don't show Auto DevOps enabled banner for projects with CI file or CI disabled. !24067
- Update GitLab Runner Helm Chart to 0.1.43. !24083
- Fix navigation style in docs. !24090 (Takuya Noguchi)
@@ -2020,7 +2020,7 @@ entry.
- Hide all tables on Pipeline when no Jobs for the Pipeline. !18540 (Takuya Noguchi)
- Fixing count on Milestones. !21446
-- Use case insensitve username lookups. !21728 (William George)
+- Use case insensitive username lookups. !21728 (William George)
- Correctly process Bamboo API result array. !21970 (Alex Lossent)
- Fix 'merged with' UI being displayed when merge request has no merge commit. !22022
- Fix broken file name navigation on MRs. !22109
@@ -2803,7 +2803,7 @@ entry.
- Fixes SVGs for empty states in job page overflowing on mobile.
- Fix checkboxes on runner admin settings - The labels are now clickable.
- Fixed IDE file row scrolling into view when hovering.
-- Accept upload files in public/uplaods/tmp when using accelerated uploads.
+- Accept upload files in public/uploads/tmp when using accelerated uploads.
- Include correct CSS file for xterm in environments page.
- Increase padding in code blocks.
- Fix: Project deletion may not log audit events during user deletion.
@@ -3689,7 +3689,7 @@ entry.
### Fixed (69 changes, 23 of them are from the community)
-- Optimize the upload migration proces. !15947
+- Optimize the upload migration process. !15947
- Import bitbucket issues that are reported by an anonymous user. !18199 (bartl)
- Fix an issue where the notification email address would be set to an unconfirmed email address. !18474
- Stop logging email information when emails are disabled. !18521 (Marc Shaw)
@@ -3817,7 +3817,7 @@ entry.
- Add a cronworker to rescue stale live traces. !18680
- Move SquashBeforeMerge vue component. !18813 (George Tsiolis)
- Add index on runner_type for ci_runners. !18897
-- Fix CarrierWave reads local files into memoery when migrates to ObjectStorage. !19102
+- Fix CarrierWave reads local files into memory when migrates to ObjectStorage. !19102
- Remove double-checked internal id generation. !19181
- Throttle updates to Project#last_repository_updated_at. !19183
- Add background migrations for archiving legacy job traces. !19194
@@ -3908,7 +3908,7 @@ entry.
- Adjust SQL and transaction Prometheus buckets.
- Adding branches through the WebUI is handled by Gitaly.
- Remove shellout implementation for Repository checksums.
-- Refs containting sha checks are done by Gitaly.
+- Refs containing sha checks are done by Gitaly.
- Finding a wiki page is done by Gitaly by default.
- Workhorse will use Gitaly to create archives.
- Workhorse to send raw diff and patch for commits.
@@ -4112,7 +4112,7 @@ entry.
- Display active sessions and allow the user to revoke any of it. !17867 (Alexis Reigel)
- Add cron job to email users on issue due date. !17985 (Stuart Nelson)
- Rubocop rule to avoid returning from a block. !18000 (Jacopo Beschi @jacopo-beschi)
-- Add the signature verfication badge to the compare view. !18245 (Marc Shaw)
+- Add the signature verification badge to the compare view. !18245 (Marc Shaw)
- Expose Deploy Token data as environment varialbes on CI/CD jobs. !18414
- Show group id in group settings. !18482 (George Tsiolis)
- Allow admins to enforce accepting Terms of Service on an instance. !18570
@@ -4850,7 +4850,7 @@ entry.
- Override group sidebar links. !16942 (George Tsiolis)
- Avoid running `PopulateForkNetworksRange`-migration multiple times. !16988
- Resolve PrepareUntrackedUploads PostgreSQL syntax error. !17019
-- Fix monaco editor features which were incompatable with GitLab CDN settings. !17021
+- Fix monaco editor features which were incompatible with GitLab CDN settings. !17021
- Fixed error 500 when removing an identity with synced attributes and visiting the profile page. !17054
- Fix cnacel edit note button reverting changes. !42462
- For issues display time of last edit of title or description instead of time of any attribute change.
@@ -5067,7 +5067,7 @@ entry.
### Performance (2 changes)
- rework indexes on redirect_routes.
-- Remove unecessary query from labels filter.
+- Remove unnecessary query from labels filter.
## 10.4.0 (2018-01-22)
@@ -5198,7 +5198,7 @@ entry.
- Add a gitlab:tcp_check rake task. !15759
- add support for sorting in tags api. !15772 (haseebeqx)
- Add Prometheus to available Cluster applications. !15895
-- Validate file status when commiting multiple files. !15922
+- Validate file status when committing multiple files. !15922
- List of avatars should never show +1. !15972 (Jacopo Beschi @jacopo-beschi)
- Do not generate NPM links for private NPM modules in blob view. !16002 (Mario de la Ossa)
- Backport fast database lookup of SSH authorized_keys from EE. !16014
@@ -5229,7 +5229,7 @@ entry.
- Fix web ide user preferences copy and buttons. !41789
- Update redis-rack to 2.0.4.
- Import some code and functionality from gitlab-shell to improve subprocess handling.
-- Update Browse file to Choose file in all occurences.
+- Update Browse file to Choose file in all occurrences.
- Bump mysql2 gem version from 0.4.5 to 0.4.10. (asaparov)
- Use a background migration for issues.closed_at.
@@ -5364,7 +5364,7 @@ entry.
- Fix graph notes number duplication. !15696 (Vladislav Kaverin)
- Fix updateEndpoint undefined error for issue_show app root. !15698
- Change boards page boards_data absolute urls to paths. !15703
-- Using appropiate services in the API for managing forks. !15709
+- Using appropriate services in the API for managing forks. !15709
- Confirming email with invalid token should no longer generate an error. !15726
- fix #39233 - 500 in merge request. !15774 (Martin Nowak)
- Use Markdown styling for new project guidelines. !15785 (Markus Koller)
@@ -5474,7 +5474,7 @@ entry.
- Stop reloading the page when using pagination and tabs - use API calls - in Pipelines table.
- Clean up schema of the "issues" table.
- Clarify wording of protected branch settings for the default branch.
-- Update svg external depencency.
+- Update svg external dependency.
- Clean up schema of the "merge_requests" table.
@@ -5644,7 +5644,7 @@ entry.
- Fix gitlab:backup rake for hashed storage based repositories. !15400
- Fix issue where clicking a GPG verification badge would scroll to the top of the page. !15407
- Update container repository path reference and allow using double underscore. !15417
-- Fix crash when navigating to second page of the group dashbaord when there are projects and groups on the first page. !15456
+- Fix crash when navigating to second page of the group dashboard when there are projects and groups on the first page. !15456
- Fix flash errors showing up on a non configured prometheus integration. !35652
- Fix timezone bug in Pikaday and upgrade Pikaday version.
- Fix arguments Import/Export error importing project merge requests.
@@ -6194,7 +6194,7 @@ entry.
- [CHANGED] Fire hooks asynchronously when creating a new job to improve performance. !13734
- [CHANGED] Improve performance for AutocompleteController#users.json. !13754 (Hiroyuki Sato)
- [CHANGED] Update the GPG verification semantics: A GPG signature must additionally match the committer in order to be verified. !13771 (Alexis Reigel)
-- [CHANGED] Support a multi-word fuzzy seach issues/merge requests on search bar. !13780 (Hiroyuki Sato)
+- [CHANGED] Support a multi-word fuzzy search issues/merge requests on search bar. !13780 (Hiroyuki Sato)
- [CHANGED] Default LDAP config "verify_certificates" to true for security. !13915
- [CHANGED] "Share with group lock" now applies to subgroups, but owner can override setting on subgroups. !13944
- [CHANGED] Make Gitaly PostUploadPack mandatory. !13953
@@ -6893,7 +6893,7 @@ entry.
## 9.3.2 (2017-06-27)
-- API: Fix optional arugments for POST :id/variables. !12474
+- API: Fix optional arguments for POST :id/variables. !12474
- Bump premailer-rails gem to 1.9.7 and its dependencies to prevent network retrieval of assets.
## 9.3.1 (2017-06-26)
@@ -6910,7 +6910,7 @@ entry.
- Refactored gitlab:app:check into SystemCheck liberary and improve some checks. !9173
- Add an ability to cancel attaching file and redesign attaching files UI. !9431 (blackst0ne)
- Add Aliyun OSS as the backup storage provider. !9721 (Yuanfei Zhu)
-- Add suport for find_local_branches GRPC from Gitaly. !10059
+- Add support for find_local_branches GRPC from Gitaly. !10059
- Allow manual bypass of auto_sign_in_with_provider with a new param. !10187 (Maxime Besson)
- Redirect to user's keys index instead of user's index after a key is deleted in the admin. !10227 (Cyril Jouve)
- Changed Blame to Annotate in the UI to promote blameless culture. !10378 (Ilya Vassilevsky)
@@ -6989,7 +6989,7 @@ entry.
- Add tag_list param to project api. !11799 (Ivan Chernov)
- Add changelog for improved Registry description. !11816
- Automatically adjust project settings to match changes in project visibility. !11831
-- Add slugify project path to CI enviroment variables. !11838 (Ivan Chernov)
+- Add slugify project path to CI environment variables. !11838 (Ivan Chernov)
- Add all pipeline sources as special keywords to 'only' and 'except'. !11844 (Filip Krakowski)
- Allow pulling of container images using personal access tokens. !11845
- Expose import_status in Projects API. !11851 (Robin Bobbitt)
@@ -7904,7 +7904,7 @@ entry.
- Clean-up Project navigation order. !9272
- Add Runner's jobs v4 API. !9273
- Add pipeline trigger API with user permissions. !9277
-- Enhanced filter issues layout for better mobile experiance. !9280 (Pratik Borsadiya)
+- Enhanced filter issues layout for better mobile experience. !9280 (Pratik Borsadiya)
- Move babel config for instanbul to karma config. !9286 (winniehell)
- Document U2F limitations with multiple URLs. !9300
- Wrap long Project and Group titles. !9301
@@ -8085,7 +8085,7 @@ entry.
- Add badges to global dropdown.
- Changed coverage reg expression placeholder text to be more like a placeholder.
- Show members of parent groups on project members page.
-- Fix grammer issue in admin/runners.
+- Fix grammar issue in admin/runners.
- Allow slashes in slash command arguments.
- Adds paginationd and folders view to environments table.
- hide loading spinners for server-rendered sidebar fields.
@@ -8258,7 +8258,7 @@ entry.
- Allows to search within project by commit hash. (YarNayar)
- Show organisation membership and delete comment on smaller viewports, plus change comment author name to username.
- Remove turbolinks.
-- Convert pipeline action icons to svg to have them propperly positioned.
+- Convert pipeline action icons to svg to have them properly positioned.
- Remove rogue scrollbars for issue comments with inline elements.
- Align Segoe UI label text.
- Color + and - signs in diffs to increase code legibility.
@@ -8549,3 +8549,4 @@ entry.
## 8.15.8 through 0.8.0
- See [changelogs/archive.md](changelogs/archive.md)
+
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index dc1e644a101..9c6d6293b1a 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-1.6.0
+1.6.1
diff --git a/Gemfile b/Gemfile
index c22a3191c3c..0569e0649dc 100644
--- a/Gemfile
+++ b/Gemfile
@@ -347,7 +347,7 @@ group :development, :test do
# Generate Fake data
gem 'ffaker', '~> 2.10'
- gem 'capybara', '~> 2.18.0'
+ gem 'capybara', '~> 3.22.0'
gem 'capybara-screenshot', '~> 1.0.22'
gem 'selenium-webdriver', '~> 3.141'
diff --git a/Gemfile.lock b/Gemfile.lock
index 785a77bc202..1f6c8d05992 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -110,13 +110,14 @@ GEM
bundler (~> 1.2)
thor (~> 0.18)
byebug (9.1.0)
- capybara (2.18.0)
+ capybara (3.22.0)
addressable
mini_mime (>= 0.1.3)
- nokogiri (>= 1.3.3)
- rack (>= 1.0.0)
- rack-test (>= 0.5.4)
- xpath (>= 2.0, < 4.0)
+ nokogiri (~> 1.8)
+ rack (>= 1.6.0)
+ rack-test (>= 0.6.3)
+ regexp_parser (~> 1.5)
+ xpath (~> 3.2)
capybara-screenshot (1.0.22)
capybara (>= 1.0, < 4)
launchy
@@ -658,7 +659,7 @@ GEM
pry (~> 0.10)
pry-rails (0.3.6)
pry (>= 0.10.4)
- public_suffix (3.0.3)
+ public_suffix (3.1.0)
puma (3.12.0)
puma_worker_killer (0.1.0)
get_process_mem (~> 0.2)
@@ -750,7 +751,7 @@ GEM
redis-store (>= 1.2, < 2)
redis-store (1.6.0)
redis (>= 2.2, < 5)
- regexp_parser (1.4.0)
+ regexp_parser (1.5.1)
regexp_property_values (0.3.4)
representable (3.0.4)
declarative (< 0.1.0)
@@ -1040,7 +1041,7 @@ DEPENDENCIES
browser (~> 2.5)
bullet (~> 5.5.0)
bundler-audit (~> 0.5.0)
- capybara (~> 2.18.0)
+ capybara (~> 3.22.0)
capybara-screenshot (~> 1.0.22)
carrierwave (~> 1.3)
charlock_holmes (~> 0.7.5)
diff --git a/PROCESS.md b/PROCESS.md
index 3c40f658070..9e971ef7531 100644
--- a/PROCESS.md
+++ b/PROCESS.md
@@ -64,7 +64,7 @@ The milestone of an issue that is currently being worked on by a community contr
should not be set to a named GitLab milestone (e.g. 11.7, 11.8), until the associated
merge request is very close to being merged, and we will likely know in which named
GitLab milestone the issue will land. There are many factors that influence when
-a community contributor finishes an issue, or even at all. So we should set this
+a community contributor finishes an issue, or even at all. So we should set this
milestone only when we have more certainty.
Note this only applies to issues currently assigned to community contributors. For
@@ -86,21 +86,12 @@ star, smile, etc.). Some good tips about code reviews can be found in our
## Feature freeze on the 7th for the release on the 22nd
-After 7th at 23:59 (Pacific Time Zone) of each month, stable branch and RC1
-of the upcoming release (to be shipped on the 22nd) is created and deployed to GitLab.com.
-The stable branch is frozen at the most recent "qualifying commit" on master.
-A "qualifying commit" is one that is pushed before the feature freeze cutoff time
-and that passes all CI jobs (green pipeline).
+The feature freeze on the 7th has been discontinued. [Transition period overview]
+describes the change to this process. During the transition period, the only guarantee that
+a change will be included in the release on the 22nd is if the change has been
+deployed to GitLab.com prior to this date.
-Merge requests may still be merged into master during this
-period, but they will go into the _next_ release, unless they are manually
-cherry-picked into the stable branch.
-
-By freezing the stable branches 2 weeks prior to a release, we reduce the risk
-of a last minute merge request potentially breaking things.
-
-Any release candidate that gets created after this date can become a final
-release, hence the name release candidate.
+[Transition period]: https://gitlab.com/gitlab-org/release/docs/blob/21cbd409dd5f157fe252f254f3e897f01908abe2/general/deploy/auto-deploy-transition.md#transition
### Feature flags
@@ -108,15 +99,15 @@ Merge requests that make changes hidden behind a feature flag, or remove an
existing feature flag because a feature is deemed stable, may be merged (and
picked into the stable branches) up to the 19th of the month. Such merge
requests should have the ~"feature flag" label assigned, and don't require a
-corresponding exception request to be created.
+corresponding exception request to be created.
-A level of common sense should be applied when deciding whether to have a feature
+A level of common sense should be applied when deciding whether to have a feature
behind a feature flag off or on by default.
The following guidelines can be applied to help make this decision:
* If the feature is not fully ready or functioning, the feature flag should be disabled by default.
-* If the feature is ready but there are concerns about performance or impact, the feature flag should be enabled by default, but
+* If the feature is ready but there are concerns about performance or impact, the feature flag should be enabled by default, but
disabled via chatops before deployment on GitLab.com environments. If the performance concern is confirmed, the final release should have the feature flag disabled by default.
* In most other cases, the feature flag can be enabled by default.
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.vue b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
index 3e01841d563..4890f99e9d1 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_table.vue
+++ b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
@@ -2,7 +2,7 @@
import PipelinesService from '../../pipelines/services/pipelines_service';
import PipelineStore from '../../pipelines/stores/pipelines_store';
import pipelinesMixin from '../../pipelines/mixins/pipelines';
-import TablePagination from '../../vue_shared/components/table_pagination.vue';
+import TablePagination from '../../vue_shared/components/pagination/table_pagination.vue';
import { getParameterByName } from '../../lib/utils/common_utils';
import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin';
diff --git a/app/assets/javascripts/environments/components/container.vue b/app/assets/javascripts/environments/components/container.vue
index be80661223c..f8a637138ad 100644
--- a/app/assets/javascripts/environments/components/container.vue
+++ b/app/assets/javascripts/environments/components/container.vue
@@ -1,6 +1,6 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
-import TablePagination from '~/vue_shared/components/table_pagination.vue';
+import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
import containerMixin from 'ee_else_ce/environments/mixins/container_mixin';
import EnvironmentTable from '../components/environments_table.vue';
diff --git a/app/assets/javascripts/environments/mixins/environments_mixin.js b/app/assets/javascripts/environments/mixins/environments_mixin.js
index a5812b173dc..31347d95a25 100644
--- a/app/assets/javascripts/environments/mixins/environments_mixin.js
+++ b/app/assets/javascripts/environments/mixins/environments_mixin.js
@@ -11,7 +11,7 @@ import Flash from '../../flash';
import eventHub from '../event_hub';
import EnvironmentsService from '../services/environments_service';
-import tablePagination from '../../vue_shared/components/table_pagination.vue';
+import tablePagination from '../../vue_shared/components/pagination/table_pagination.vue';
import environmentTable from '../components/environments_table.vue';
import tabs from '../../vue_shared/components/navigation_tabs.vue';
import container from '../components/container.vue';
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index e41b1530226..363a8f43033 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -146,7 +146,7 @@ export default {
</div>
<component :is="rightPaneComponent" v-if="currentProjectId" />
</div>
- <ide-status-bar :file="activeFile" />
+ <ide-status-bar />
<new-modal />
</article>
</template>
diff --git a/app/assets/javascripts/ide/components/ide_status_bar.vue b/app/assets/javascripts/ide/components/ide_status_bar.vue
index ce577ae85b0..206b8341aad 100644
--- a/app/assets/javascripts/ide/components/ide_status_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_status_bar.vue
@@ -1,5 +1,6 @@
<script>
import { mapActions, mapState, mapGetters } from 'vuex';
+import IdeStatusList from 'ee_else_ce/ide/components/ide_status_list.vue';
import icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import timeAgoMixin from '~/vue_shared/mixins/timeago';
@@ -12,18 +13,12 @@ export default {
icon,
userAvatarImage,
CiIcon,
+ IdeStatusList,
},
directives: {
tooltip,
},
mixins: [timeAgoMixin],
- props: {
- file: {
- type: Object,
- required: false,
- default: null,
- },
- },
data() {
return {
lastCommitFormatedAge: null,
@@ -125,11 +120,6 @@ export default {
>{{ lastCommitFormatedAge }}</time
>
</div>
- <div v-if="file" class="ide-status-file">{{ file.name }}</div>
- <div v-if="file" class="ide-status-file">{{ file.eol }}</div>
- <div v-if="file && !file.binary" class="ide-status-file">
- {{ file.editorRow }}:{{ file.editorColumn }}
- </div>
- <div v-if="file" class="ide-status-file">{{ file.fileLanguage }}</div>
+ <ide-status-list class="ml-auto" />
</footer>
</template>
diff --git a/app/assets/javascripts/ide/components/ide_status_list.vue b/app/assets/javascripts/ide/components/ide_status_list.vue
new file mode 100644
index 00000000000..364e3f081a1
--- /dev/null
+++ b/app/assets/javascripts/ide/components/ide_status_list.vue
@@ -0,0 +1,23 @@
+<script>
+import { mapGetters } from 'vuex';
+
+export default {
+ computed: {
+ ...mapGetters(['activeFile']),
+ },
+};
+</script>
+
+<template>
+ <div class="ide-status-list d-flex">
+ <template v-if="activeFile">
+ <div class="ide-status-file">{{ activeFile.name }}</div>
+ <div class="ide-status-file">{{ activeFile.eol }}</div>
+ <div v-if="!activeFile.binary" class="ide-status-file">
+ {{ activeFile.editorRow }}:{{ activeFile.editorColumn }}
+ </div>
+ <div class="ide-status-file">{{ activeFile.fileLanguage }}</div>
+ </template>
+ <slot></slot>
+ </div>
+</template>
diff --git a/app/assets/javascripts/lib/utils/invalid_url.js b/app/assets/javascripts/lib/utils/invalid_url.js
new file mode 100644
index 00000000000..481bd059fc9
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/invalid_url.js
@@ -0,0 +1,6 @@
+/**
+ * Invalid URL that ensures we don't make a network request
+ * Can be used as a default value for URLs. Using an empty
+ * string can still result in request being made to the current page
+ */
+export default 'https://invalid';
diff --git a/app/assets/javascripts/monitoring/components/charts/area.vue b/app/assets/javascripts/monitoring/components/charts/area.vue
index c43791f2426..9de4e96e4da 100644
--- a/app/assets/javascripts/monitoring/components/charts/area.vue
+++ b/app/assets/javascripts/monitoring/components/charts/area.vue
@@ -1,7 +1,7 @@
<script>
import { GlAreaChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts';
import dateFormat from 'dateformat';
-import { debounceByAnimationFrame } from '~/lib/utils/common_utils';
+import { debounceByAnimationFrame, roundOffFloat } from '~/lib/utils/common_utils';
import { getSvgIconPathContent } from '~/lib/utils/icon_utils';
import Icon from '~/vue_shared/components/icon.vue';
import { chartHeight, graphTypes, lineTypes } from '../../constants';
@@ -111,7 +111,7 @@ export default {
yAxis: {
name: this.yAxisLabel,
axisLabel: {
- formatter: value => value.toFixed(3),
+ formatter: num => roundOffFloat(num, 3).toString(),
},
},
series: this.scatterSeries,
@@ -227,6 +227,7 @@ export default {
[this.primaryColor] = chart.getOption().color;
},
onResize() {
+ if (!this.$refs.areaChart) return;
const { width } = this.$refs.areaChart.$el.getBoundingClientRect();
this.width = width;
},
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index 2314f7b80cf..d716fc211ca 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -1,18 +1,12 @@
<script>
-import {
- GlButton,
- GlDropdown,
- GlDropdownItem,
- GlModal,
- GlModalDirective,
- GlLink,
-} from '@gitlab/ui';
+import { GlButton, GlDropdown, GlDropdownItem, GlModal, GlModalDirective } from '@gitlab/ui';
import _ from 'underscore';
import { mapActions, mapState } from 'vuex';
import { s__ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import '~/vue_shared/mixins/is_ee';
import { getParameterValues } from '~/lib/utils/url_utility';
+import invalidUrl from '~/lib/utils/invalid_url';
import MonitorAreaChart from './charts/area.vue';
import GraphGroup from './graph_group.vue';
import EmptyState from './empty_state.vue';
@@ -31,7 +25,6 @@ export default {
GlButton,
GlDropdown,
GlDropdownItem,
- GlLink,
GlModal,
},
directives: {
@@ -119,6 +112,11 @@ export default {
type: String,
required: true,
},
+ dashboardEndpoint: {
+ type: String,
+ required: false,
+ default: invalidUrl,
+ },
},
data() {
return {
@@ -139,13 +137,19 @@ export default {
'showEmptyState',
'environments',
'deploymentData',
+ 'metricsWithData',
+ 'useDashboardEndpoint',
]),
+ groupsWithData() {
+ return this.groups.filter(group => this.chartsWithData(group.metrics).length > 0);
+ },
},
created() {
this.setEndpoints({
metricsEndpoint: this.metricsEndpoint,
environmentsEndpoint: this.environmentsEndpoint,
deploymentsEndpoint: this.deploymentEndpoint,
+ dashboardEndpoint: this.dashboardEndpoint,
});
this.timeWindows = timeWindows;
@@ -183,7 +187,16 @@ export default {
'fetchData',
'setGettingStartedEmptyState',
'setEndpoints',
+ 'setDashboardEnabled',
]),
+ chartsWithData(charts) {
+ if (!this.useDashboardEndpoint) {
+ return charts;
+ }
+ return charts.filter(chart =>
+ chart.metrics.some(metric => this.metricsWithData.includes(metric.metric_id)),
+ );
+ },
getGraphAlerts(queries) {
if (!this.allAlerts) return {};
const metricIdsForChart = queries.map(q => q.metricId);
@@ -255,7 +268,9 @@ export default {
v-for="(value, key) in timeWindows"
:key="key"
:active="activeTimeWindow(key)"
- ><gl-link :href="setTimeWindowParameter(key)">{{ value }}</gl-link></gl-dropdown-item
+ :href="setTimeWindowParameter(key)"
+ active-class="active"
+ >{{ value }}</gl-dropdown-item
>
</gl-dropdown>
</div>
@@ -307,13 +322,13 @@ export default {
</div>
</div>
<graph-group
- v-for="(groupData, index) in groups"
+ v-for="(groupData, index) in groupsWithData"
:key="index"
:name="groupData.group"
:show-panels="showPanels"
>
<monitor-area-chart
- v-for="(graphData, graphIndex) in groupData.metrics"
+ v-for="(graphData, graphIndex) in chartsWithData(groupData.metrics)"
:key="graphIndex"
:graph-data="graphData"
:deployment-data="deploymentData"
diff --git a/app/assets/javascripts/monitoring/monitoring_bundle.js b/app/assets/javascripts/monitoring/monitoring_bundle.js
index 62c0f44c1e6..1d33537b3b2 100644
--- a/app/assets/javascripts/monitoring/monitoring_bundle.js
+++ b/app/assets/javascripts/monitoring/monitoring_bundle.js
@@ -7,6 +7,11 @@ export default (props = {}) => {
const el = document.getElementById('prometheus-graphs');
if (el && el.dataset) {
+ store.dispatch(
+ 'monitoringDashboard/setDashboardEnabled',
+ gon.features.environmentMetricsUsePrometheusEndpoint,
+ );
+
// eslint-disable-next-line no-new
new Vue({
el,
diff --git a/app/assets/javascripts/monitoring/stores/actions.js b/app/assets/javascripts/monitoring/stores/actions.js
index 63c23e8449d..49ce722b838 100644
--- a/app/assets/javascripts/monitoring/stores/actions.js
+++ b/app/assets/javascripts/monitoring/stores/actions.js
@@ -35,6 +35,21 @@ export const setEndpoints = ({ commit }, endpoints) => {
commit(types.SET_ENDPOINTS, endpoints);
};
+export const setDashboardEnabled = ({ commit }, enabled) => {
+ commit(types.SET_DASHBOARD_ENABLED, enabled);
+};
+
+export const requestMetricsDashboard = ({ commit }) => {
+ commit(types.REQUEST_METRICS_DATA);
+};
+export const receiveMetricsDashboardSuccess = ({ commit, dispatch }, { response, params }) => {
+ commit(types.RECEIVE_METRICS_DATA_SUCCESS, response.dashboard.panel_groups);
+ dispatch('fetchPrometheusMetrics', params);
+};
+export const receiveMetricsDashboardFailure = ({ commit }, error) => {
+ commit(types.RECEIVE_METRICS_DATA_FAILURE, error);
+};
+
export const requestMetricsData = ({ commit }) => commit(types.REQUEST_METRICS_DATA);
export const receiveMetricsDataSuccess = ({ commit }, data) =>
commit(types.RECEIVE_METRICS_DATA_SUCCESS, data);
@@ -56,6 +71,10 @@ export const fetchData = ({ dispatch }, params) => {
};
export const fetchMetricsData = ({ state, dispatch }, params) => {
+ if (state.useDashboardEndpoint) {
+ return dispatch('fetchDashboard', params);
+ }
+
dispatch('requestMetricsData');
return backOffRequest(() => axios.get(state.metricsEndpoint, { params }))
@@ -73,6 +92,77 @@ export const fetchMetricsData = ({ state, dispatch }, params) => {
});
};
+export const fetchDashboard = ({ state, dispatch }, params) => {
+ dispatch('requestMetricsDashboard');
+
+ return axios
+ .get(state.dashboardEndpoint, { params })
+ .then(resp => resp.data)
+ .then(response => {
+ dispatch('receiveMetricsDashboardSuccess', { response, params });
+ })
+ .catch(error => {
+ dispatch('receiveMetricsDashboardFailure', error);
+ createFlash(s__('Metrics|There was an error while retrieving metrics'));
+ });
+};
+
+function fetchPrometheusResult(prometheusEndpoint, params) {
+ return backOffRequest(() => axios.get(prometheusEndpoint, { params }))
+ .then(res => res.data)
+ .then(response => {
+ if (response.status === 'error') {
+ throw new Error(response.error);
+ }
+
+ return response.data.result;
+ });
+}
+
+/**
+ * Returns list of metrics in data.result
+ * {"status":"success", "data":{"resultType":"matrix","result":[]}}
+ *
+ * @param {metric} metric
+ */
+export const fetchPrometheusMetric = ({ commit }, { metric, params }) => {
+ const { start, end } = params;
+ const timeDiff = end - start;
+
+ const minStep = 60;
+ const queryDataPoints = 600;
+ const step = Math.max(minStep, Math.ceil(timeDiff / queryDataPoints));
+
+ const queryParams = {
+ start,
+ end,
+ step,
+ };
+
+ return fetchPrometheusResult(metric.prometheus_endpoint_path, queryParams).then(result => {
+ commit(types.SET_QUERY_RESULT, { metricId: metric.metric_id, result });
+ });
+};
+
+export const fetchPrometheusMetrics = ({ state, commit, dispatch }, params) => {
+ commit(types.REQUEST_METRICS_DATA);
+
+ const promises = [];
+ state.groups.forEach(group => {
+ group.panels.forEach(panel => {
+ panel.metrics.forEach(metric => {
+ promises.push(dispatch('fetchPrometheusMetric', { metric, params }));
+ });
+ });
+ });
+
+ return Promise.all(promises).then(() => {
+ if (state.metricsWithData.length === 0) {
+ commit(types.SET_NO_DATA_EMPTY_STATE);
+ }
+ });
+};
+
export const fetchDeploymentsData = ({ state, dispatch }) => {
if (!state.deploymentEndpoint) {
return Promise.resolve([]);
diff --git a/app/assets/javascripts/monitoring/stores/mutation_types.js b/app/assets/javascripts/monitoring/stores/mutation_types.js
index 3fd9e07fa8b..63894e83362 100644
--- a/app/assets/javascripts/monitoring/stores/mutation_types.js
+++ b/app/assets/javascripts/monitoring/stores/mutation_types.js
@@ -7,6 +7,9 @@ export const RECEIVE_DEPLOYMENTS_DATA_FAILURE = 'RECEIVE_DEPLOYMENTS_DATA_FAILUR
export const REQUEST_ENVIRONMENTS_DATA = 'REQUEST_ENVIRONMENTS_DATA';
export const RECEIVE_ENVIRONMENTS_DATA_SUCCESS = 'RECEIVE_ENVIRONMENTS_DATA_SUCCESS';
export const RECEIVE_ENVIRONMENTS_DATA_FAILURE = 'RECEIVE_ENVIRONMENTS_DATA_FAILURE';
+export const SET_QUERY_RESULT = 'SET_QUERY_RESULT';
export const SET_TIME_WINDOW = 'SET_TIME_WINDOW';
+export const SET_DASHBOARD_ENABLED = 'SET_DASHBOARD_ENABLED';
export const SET_ENDPOINTS = 'SET_ENDPOINTS';
export const SET_GETTING_STARTED_EMPTY_STATE = 'SET_GETTING_STARTED_EMPTY_STATE';
+export const SET_NO_DATA_EMPTY_STATE = 'SET_NO_DATA_EMPTY_STATE';
diff --git a/app/assets/javascripts/monitoring/stores/mutations.js b/app/assets/javascripts/monitoring/stores/mutations.js
index c1779333d75..d4b816e2717 100644
--- a/app/assets/javascripts/monitoring/stores/mutations.js
+++ b/app/assets/javascripts/monitoring/stores/mutations.js
@@ -1,5 +1,6 @@
+import Vue from 'vue';
import * as types from './mutation_types';
-import { normalizeMetrics, sortMetrics } from './utils';
+import { normalizeMetrics, sortMetrics, normalizeQueryResult } from './utils';
export default {
[types.REQUEST_METRICS_DATA](state) {
@@ -7,10 +8,24 @@ export default {
state.showEmptyState = true;
},
[types.RECEIVE_METRICS_DATA_SUCCESS](state, groupData) {
- state.groups = groupData.map(group => ({
- ...group,
- metrics: normalizeMetrics(sortMetrics(group.metrics)),
- }));
+ state.groups = groupData.map(group => {
+ let { metrics } = group;
+
+ // for backwards compatibility, and to limit Vue template changes:
+ // for each group alias panels to metrics
+ // for each panel alias metrics to queries
+ if (state.useDashboardEndpoint) {
+ metrics = group.panels.map(panel => ({
+ ...panel,
+ queries: panel.metrics,
+ }));
+ }
+
+ return {
+ ...group,
+ metrics: normalizeMetrics(sortMetrics(metrics)),
+ };
+ });
if (!state.groups.length) {
state.emptyState = 'noData';
@@ -34,12 +49,40 @@ export default {
[types.RECEIVE_ENVIRONMENTS_DATA_FAILURE](state) {
state.environments = [];
},
+ [types.SET_QUERY_RESULT](state, { metricId, result }) {
+ if (!metricId || !result || result.length === 0) {
+ return;
+ }
+
+ state.showEmptyState = false;
+
+ state.groups.forEach(group => {
+ group.metrics.forEach(metric => {
+ metric.queries.forEach(query => {
+ if (query.metric_id === metricId) {
+ state.metricsWithData.push(metricId);
+ // ensure dates/numbers are correctly formatted for charts
+ const normalizedResults = result.map(normalizeQueryResult);
+ Vue.set(query, 'result', Object.freeze(normalizedResults));
+ }
+ });
+ });
+ });
+ },
[types.SET_ENDPOINTS](state, endpoints) {
state.metricsEndpoint = endpoints.metricsEndpoint;
state.environmentsEndpoint = endpoints.environmentsEndpoint;
state.deploymentsEndpoint = endpoints.deploymentsEndpoint;
+ state.dashboardEndpoint = endpoints.dashboardEndpoint;
+ },
+ [types.SET_DASHBOARD_ENABLED](state, enabled) {
+ state.useDashboardEndpoint = enabled;
},
[types.SET_GETTING_STARTED_EMPTY_STATE](state) {
state.emptyState = 'gettingStarted';
},
+ [types.SET_NO_DATA_EMPTY_STATE](state) {
+ state.showEmptyState = true;
+ state.emptyState = 'noData';
+ },
};
diff --git a/app/assets/javascripts/monitoring/stores/state.js b/app/assets/javascripts/monitoring/stores/state.js
index 5103122612a..c33529cd588 100644
--- a/app/assets/javascripts/monitoring/stores/state.js
+++ b/app/assets/javascripts/monitoring/stores/state.js
@@ -1,12 +1,17 @@
+import invalidUrl from '~/lib/utils/invalid_url';
+
export default () => ({
hasMetrics: false,
showPanels: true,
metricsEndpoint: null,
environmentsEndpoint: null,
deploymentsEndpoint: null,
+ dashboardEndpoint: invalidUrl,
+ useDashboardEndpoint: false,
emptyState: 'gettingStarted',
showEmptyState: true,
groups: [],
deploymentData: [],
environments: [],
+ metricsWithData: [],
});
diff --git a/app/assets/javascripts/monitoring/stores/utils.js b/app/assets/javascripts/monitoring/stores/utils.js
index 9216554ecbf..84e1f1c4c20 100644
--- a/app/assets/javascripts/monitoring/stores/utils.js
+++ b/app/assets/javascripts/monitoring/stores/utils.js
@@ -58,6 +58,14 @@ export const sortMetrics = metrics =>
.sortBy('weight')
.value();
+export const normalizeQueryResult = timeSeries => ({
+ ...timeSeries,
+ values: timeSeries.values.map(([timestamp, value]) => [
+ new Date(timestamp * 1000).toISOString(),
+ Number(value),
+ ]),
+});
+
export const normalizeMetrics = metrics => {
const groupedMetrics = groupQueriesByChartInfo(metrics);
@@ -66,13 +74,7 @@ export const normalizeMetrics = metrics => {
...query,
// custom metrics do not require a label, so we should ensure this attribute is defined
label: query.label || metric.y_label,
- result: query.result.map(result => ({
- ...result,
- values: result.values.map(([timestamp, value]) => [
- new Date(timestamp * 1000).toISOString(),
- Number(value),
- ]),
- })),
+ result: (query.result || []).map(normalizeQueryResult),
}));
return {
diff --git a/app/assets/javascripts/pipelines/components/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines.vue
index 9dcea557b32..d730ef41b1a 100644
--- a/app/assets/javascripts/pipelines/components/pipelines.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines.vue
@@ -4,7 +4,7 @@ import { __, sprintf, s__ } from '../../locale';
import createFlash from '../../flash';
import PipelinesService from '../services/pipelines_service';
import pipelinesMixin from '../mixins/pipelines';
-import TablePagination from '../../vue_shared/components/table_pagination.vue';
+import TablePagination from '../../vue_shared/components/pagination/table_pagination.vue';
import NavigationTabs from '../../vue_shared/components/navigation_tabs.vue';
import NavigationControls from './nav_controls.vue';
import { getParameterByName } from '../../lib/utils/common_utils';
diff --git a/app/assets/javascripts/registry/components/table_registry.vue b/app/assets/javascripts/registry/components/table_registry.vue
index 81fe0a48c06..1e4dfe76b26 100644
--- a/app/assets/javascripts/registry/components/table_registry.vue
+++ b/app/assets/javascripts/registry/components/table_registry.vue
@@ -4,7 +4,7 @@ import { GlButton, GlTooltipDirective } from '@gitlab/ui';
import { n__ } from '../../locale';
import createFlash from '../../flash';
import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
-import TablePagination from '../../vue_shared/components/table_pagination.vue';
+import TablePagination from '../../vue_shared/components/pagination/table_pagination.vue';
import Icon from '../../vue_shared/components/icon.vue';
import timeagoMixin from '../../vue_shared/mixins/timeago';
import { errorMessages, errorMessagesTypes } from '../constants';
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
index 88e1ccbaf35..5958c2cf87e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
@@ -1,15 +1,19 @@
<script>
+import _ from 'underscore';
+import autoMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/auto_merge';
import Flash from '../../../flash';
import statusIcon from '../mr_widget_status_icon.vue';
import MrWidgetAuthor from '../../components/mr_widget_author.vue';
import eventHub from '../../event_hub';
+import { AUTO_MERGE_STRATEGIES } from '../../constants';
export default {
- name: 'MRWidgetMergeWhenPipelineSucceeds',
+ name: 'MRWidgetAutoMergeEnabled',
components: {
MrWidgetAuthor,
statusIcon,
},
+ mixins: [autoMergeMixin],
props: {
mr: {
type: Object,
@@ -57,7 +61,7 @@ export default {
removeSourceBranch() {
const options = {
sha: this.mr.sha,
- auto_merge_strategy: 'merge_when_pipeline_succeeds',
+ auto_merge_strategy: this.mr.autoMergeStrategy,
should_remove_source_branch: true,
};
@@ -66,7 +70,7 @@ export default {
.merge(options)
.then(res => res.data)
.then(data => {
- if (data.status === 'merge_when_pipeline_succeeds') {
+ if (_.includes(AUTO_MERGE_STRATEGIES, data.status)) {
eventHub.$emit('MRWidgetUpdateRequested');
}
})
@@ -84,9 +88,9 @@ export default {
<div class="media-body">
<h4 class="d-flex align-items-start">
<span class="append-right-10">
- {{ s__('mrWidget|Set by') }}
+ <span class="js-status-text-before-author">{{ statusTextBeforeAuthor }}</span>
<mr-widget-author :author="mr.setToAutoMergeBy" />
- {{ s__('mrWidget|to be merged automatically when the pipeline succeeds') }}
+ <span class="js-status-text-after-author">{{ statusTextAfterAuthor }}</span>
</span>
<a
v-if="mr.canCancelAutomaticMerge"
@@ -97,7 +101,7 @@ export default {
@click.prevent="cancelAutomaticMerge"
>
<i v-if="isCancellingAutoMerge" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
- {{ s__('mrWidget|Cancel automatic merge') }}
+ {{ cancelButtonText }}
</a>
</h4>
<section class="mr-info-list">
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
index 615d59a7b8e..ca1b4a57717 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
@@ -1,4 +1,5 @@
<script>
+import _ from 'underscore';
import successSvg from 'icons/_icon_status_success.svg';
import warningSvg from 'icons/_icon_status_warning.svg';
import simplePoll from '~/lib/utils/simple_poll';
@@ -12,6 +13,7 @@ import SquashBeforeMerge from './squash_before_merge.vue';
import CommitsHeader from './commits_header.vue';
import CommitEdit from './commit_edit.vue';
import CommitMessageDropdown from './commit_message_dropdown.vue';
+import { AUTO_MERGE_STRATEGIES } from '../../constants';
export default {
name: 'ReadyToMerge',
@@ -30,8 +32,6 @@ export default {
data() {
return {
removeSourceBranch: this.mr.shouldRemoveSourceBranch,
- mergeWhenBuildSucceeds: false,
- autoMergeStrategy: undefined,
isMakingRequest: false,
isMergingImmediately: false,
commitMessage: this.mr.commitMessage,
@@ -42,18 +42,18 @@ export default {
};
},
computed: {
- shouldShowAutoMergeText() {
- return this.mr.isPipelineActive;
+ isAutoMergeAvailable() {
+ return !_.isEmpty(this.mr.availableAutoMergeStrategies);
},
status() {
- const { pipeline, isPipelineActive, isPipelineFailed, hasCI, ciStatus } = this.mr;
+ const { pipeline, isPipelineFailed, hasCI, ciStatus } = this.mr;
if (hasCI && !ciStatus) {
return 'failed';
+ } else if (this.isAutoMergeAvailable) {
+ return 'pending';
} else if (!pipeline) {
return 'success';
- } else if (isPipelineActive) {
- return 'pending';
} else if (isPipelineFailed) {
return 'failed';
}
@@ -87,14 +87,14 @@ export default {
mergeButtonText() {
if (this.isMergingImmediately) {
return __('Merge in progress');
- } else if (this.shouldShowAutoMergeText) {
- return __('Merge when pipeline succeeds');
+ } else if (this.isAutoMergeAvailable) {
+ return this.autoMergeText;
}
- return 'Merge';
+ return __('Merge');
},
shouldShowMergeOptionsDropdown() {
- return this.mr.isPipelineActive && !this.mr.onlyAllowMergeIfPipelineSucceeds;
+ return this.isAutoMergeAvailable && !this.mr.onlyAllowMergeIfPipelineSucceeds;
},
isRemoveSourceBranchButtonDisabled() {
return this.isMergeButtonDisabled;
@@ -104,7 +104,7 @@ export default {
return enableSquashBeforeMerge && commitsCount > 1;
},
shouldShowMergeControls() {
- return this.mr.isMergeAllowed || this.shouldShowAutoMergeText;
+ return this.mr.isMergeAllowed || this.isAutoMergeAvailable;
},
shouldShowSquashEdit() {
return this.squashBeforeMerge && this.shouldShowSquashBeforeMerge;
@@ -118,20 +118,15 @@ export default {
const { commitMessageWithDescription, commitMessage } = this.mr;
this.commitMessage = includeDescription ? commitMessageWithDescription : commitMessage;
},
- handleMergeButtonClick(mergeWhenBuildSucceeds, mergeImmediately) {
- // TODO: Remove no-param-reassign
- if (mergeWhenBuildSucceeds === undefined) {
- mergeWhenBuildSucceeds = this.mr.isPipelineActive; // eslint-disable-line no-param-reassign
- } else if (mergeImmediately) {
+ handleMergeButtonClick(useAutoMerge, mergeImmediately = false) {
+ if (mergeImmediately) {
this.isMergingImmediately = true;
}
- this.autoMergeStrategy = mergeWhenBuildSucceeds ? 'merge_when_pipeline_succeeds' : undefined;
-
const options = {
sha: this.mr.sha,
commit_message: this.commitMessage,
- auto_merge_strategy: this.autoMergeStrategy,
+ auto_merge_strategy: useAutoMerge ? this.mr.preferredAutoMergeStrategy : undefined,
should_remove_source_branch: this.removeSourceBranch === true,
squash: this.squashBeforeMerge,
squash_commit_message: this.squashCommitMessage,
@@ -144,7 +139,7 @@ export default {
.then(data => {
const hasError = data.status === 'failed' || data.status === 'hook_validation_error';
- if (data.status === 'merge_when_pipeline_succeeds') {
+ if (_.includes(AUTO_MERGE_STRATEGIES, data.status)) {
eventHub.$emit('MRWidgetUpdateRequested');
} else if (data.status === 'success') {
this.initiateMergePolling();
@@ -242,13 +237,13 @@ export default {
:class="mergeButtonClass"
type="button"
class="qa-merge-button"
- @click="handleMergeButtonClick()"
+ @click="handleMergeButtonClick(isAutoMergeAvailable)"
>
<i v-if="isMakingRequest" class="fa fa-spinner fa-spin" aria-hidden="true"></i>
{{ mergeButtonText }}
</button>
<button
- v-if="shouldShowMergeOptionsDropdown"
+ v-if="isAutoMergeAvailable"
:disabled="isMergeButtonDisabled"
type="button"
class="btn btn-sm btn-info dropdown-toggle js-merge-moment"
@@ -264,15 +259,13 @@ export default {
>
<li>
<a
- class="merge_when_pipeline_succeeds qa-merge-when-pipeline-succeeds-option"
+ class="auto_merge_enabled qa-merge-when-pipeline-succeeds-option"
href="#"
@click.prevent="handleMergeButtonClick(true)"
>
<span class="media">
<span class="merge-opt-icon" aria-hidden="true" v-html="successSvg"></span>
- <span class="media-body merge-opt-title">{{
- __('Merge when pipeline succeeds')
- }}</span>
+ <span class="media-body merge-opt-title">{{ autoMergeText }}</span>
</span>
</a>
</li>
diff --git a/app/assets/javascripts/vue_merge_request_widget/constants.js b/app/assets/javascripts/vue_merge_request_widget/constants.js
index 0a29d55fbd6..3e65bdf0cb0 100644
--- a/app/assets/javascripts/vue_merge_request_widget/constants.js
+++ b/app/assets/javascripts/vue_merge_request_widget/constants.js
@@ -3,3 +3,13 @@ export const DANGER = 'danger';
export const WARNING_MESSAGE_CLASS = 'warning_message';
export const DANGER_MESSAGE_CLASS = 'danger_message';
+
+export const MWPS_MERGE_STRATEGY = 'merge_when_pipeline_succeeds';
+export const ATMTWPS_MERGE_STRATEGY = 'add_to_merge_train_when_pipeline_succeeds';
+export const MT_MERGE_STRATEGY = 'merge_train';
+
+export const AUTO_MERGE_STRATEGIES = [
+ MWPS_MERGE_STRATEGY,
+ ATMTWPS_MERGE_STRATEGY,
+ MT_MERGE_STRATEGY,
+];
diff --git a/app/assets/javascripts/vue_merge_request_widget/mixins/auto_merge.js b/app/assets/javascripts/vue_merge_request_widget/mixins/auto_merge.js
new file mode 100644
index 00000000000..23e140623cc
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/mixins/auto_merge.js
@@ -0,0 +1,15 @@
+import { s__ } from '~/locale';
+
+export default {
+ computed: {
+ statusTextBeforeAuthor() {
+ return s__('mrWidget|Set by');
+ },
+ statusTextAfterAuthor() {
+ return s__('mrWidget|to be merged automatically when the pipeline succeeds');
+ },
+ cancelButtonText() {
+ return s__('mrWidget|Cancel automatic merge');
+ },
+ },
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
index b2e64506472..116d537c463 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
+++ b/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
@@ -1,3 +1,5 @@
+import { __ } from '~/locale';
+
export default {
computed: {
isMergeButtonDisabled() {
@@ -9,5 +11,9 @@ export default {
this.mr.preventMerge,
);
},
+ autoMergeText() {
+ // MWPS is currently the only auto merge strategy available in CE
+ return __('Merge when pipeline succeeds');
+ },
},
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index d02bb2f341d..41386178a1e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -29,7 +29,7 @@ import UnresolvedDiscussionsState from './components/states/unresolved_discussio
import PipelineBlockedState from './components/states/mr_widget_pipeline_blocked.vue';
import PipelineFailedState from './components/states/pipeline_failed.vue';
import FailedToMerge from './components/states/mr_widget_failed_to_merge.vue';
-import MergeWhenPipelineSucceedsState from './components/states/mr_widget_merge_when_pipeline_succeeds.vue';
+import MrWidgetAutoMergeEnabled from './components/states/mr_widget_auto_merge_enabled.vue';
import AutoMergeFailed from './components/states/mr_widget_auto_merge_failed.vue';
import CheckingState from './components/states/mr_widget_checking.vue';
import eventHub from './event_hub';
@@ -64,7 +64,7 @@ export default {
'mr-widget-unresolved-discussions': UnresolvedDiscussionsState,
'mr-widget-pipeline-blocked': PipelineBlockedState,
'mr-widget-pipeline-failed': PipelineFailedState,
- 'mr-widget-merge-when-pipeline-succeeds': MergeWhenPipelineSucceedsState,
+ MrWidgetAutoMergeEnabled,
'mr-widget-auto-merge-failed': AutoMergeFailed,
'mr-widget-rebase': RebaseState,
SourceBranchRemovalStatus,
@@ -117,14 +117,6 @@ export default {
this.mr.mergePipelinesEnabled && this.mr.sourceProjectId !== this.mr.targetProjectId,
);
},
- showTargetBranchAdvancedError() {
- return Boolean(
- this.mr.isOpen &&
- this.mr.pipeline &&
- this.mr.pipeline.target_sha &&
- this.mr.pipeline.target_sha !== this.mr.targetBranchSha,
- );
- },
mergeError() {
return sprintf(s__('mrWidget|Merge failed: %{mergeError}. Please try again.'), {
mergeError: this.mr.mergeError,
@@ -363,18 +355,6 @@ export default {
}}
</mr-widget-alert-message>
- <mr-widget-alert-message
- v-if="showTargetBranchAdvancedError"
- type="danger"
- :help-path="mr.mergeRequestPipelinesHelpPath"
- >
- {{
- s__(
- 'mrWidget|The target branch has advanced, which invalidates the merge request pipeline. Please update the source branch and retry merging',
- )
- }}
- </mr-widget-alert-message>
-
<mr-widget-alert-message v-if="mr.mergeError" type="danger">
{{ mergeError }}
</mr-widget-alert-message>
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
index 32badb0fb08..bfa3e7f4a59 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
@@ -1,7 +1,9 @@
import Timeago from 'timeago.js';
+import _ from 'underscore';
import getStateKey from 'ee_else_ce/vue_merge_request_widget/stores/get_state_key';
import { stateKey } from './state_maps';
import { formatDate } from '../../lib/utils/datetime_utility';
+import { ATMTWPS_MERGE_STRATEGY, MT_MERGE_STRATEGY, MWPS_MERGE_STRATEGY } from '../constants';
export default class MergeRequestStore {
constructor(data) {
@@ -77,6 +79,10 @@ export default class MergeRequestStore {
this.onlyAllowMergeIfPipelineSucceeds = data.only_allow_merge_if_pipeline_succeeds || false;
this.autoMergeEnabled = Boolean(data.auto_merge_enabled);
this.autoMergeStrategy = data.auto_merge_strategy;
+ this.availableAutoMergeStrategies = data.available_auto_merge_strategies;
+ this.preferredAutoMergeStrategy = MergeRequestStore.getPreferredAutoMergeStrategy(
+ this.availableAutoMergeStrategies,
+ );
this.mergePath = data.merge_path;
this.ffOnlyEnabled = data.ff_only_enabled;
this.shouldBeRebased = Boolean(data.should_be_rebased);
@@ -104,7 +110,9 @@ export default class MergeRequestStore {
this.sourceProjectFullPath = data.source_project_full_path;
this.sourceProjectId = data.source_project_id;
this.targetProjectId = data.target_project_id;
- this.mergePipelinesEnabled = data.merge_pipelines_enabled;
+ this.mergePipelinesEnabled = Boolean(data.merge_pipelines_enabled);
+ this.mergeTrainsCount = data.merge_trains_count || 0;
+ this.mergeTrainIndex = data.merge_train_index;
// Cherry-pick and Revert actions related
this.canCherryPickInCurrentMR = currentUser.can_cherry_pick_on_current_merge_request || false;
@@ -204,4 +212,16 @@ export default class MergeRequestStore {
return timeagoInstance.format(date);
}
+
+ static getPreferredAutoMergeStrategy(availableAutoMergeStrategies) {
+ if (_.includes(availableAutoMergeStrategies, ATMTWPS_MERGE_STRATEGY)) {
+ return ATMTWPS_MERGE_STRATEGY;
+ } else if (_.includes(availableAutoMergeStrategies, MT_MERGE_STRATEGY)) {
+ return MT_MERGE_STRATEGY;
+ } else if (_.includes(availableAutoMergeStrategies, MWPS_MERGE_STRATEGY)) {
+ return MWPS_MERGE_STRATEGY;
+ }
+
+ return undefined;
+ }
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js b/app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js
index 48bc6a867f4..28507bba3e5 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js
@@ -13,7 +13,7 @@ const stateToComponentMap = {
unresolvedDiscussions: 'mr-widget-unresolved-discussions',
pipelineBlocked: 'mr-widget-pipeline-blocked',
pipelineFailed: 'mr-widget-pipeline-failed',
- autoMergeEnabled: 'mr-widget-merge-when-pipeline-succeeds',
+ autoMergeEnabled: 'mr-widget-auto-merge-enabled',
failedToMerge: 'mr-widget-failed-to-merge',
autoMergeFailed: 'mr-widget-auto-merge-failed',
shaMismatch: 'sha-mismatch',
diff --git a/app/assets/javascripts/vue_shared/components/commit.vue b/app/assets/javascripts/vue_shared/components/commit.vue
index 3ba946e6447..a1168fa0f1e 100644
--- a/app/assets/javascripts/vue_shared/components/commit.vue
+++ b/app/assets/javascripts/vue_shared/components/commit.vue
@@ -1,6 +1,7 @@
<script>
import _ from 'underscore';
import { GlTooltipDirective, GlLink } from '@gitlab/ui';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import UserAvatarLink from './user_avatar/user_avatar_link.vue';
import Icon from '../../vue_shared/components/icon.vue';
@@ -12,6 +13,7 @@ export default {
UserAvatarLink,
Icon,
GlLink,
+ TooltipOnTruncate,
},
props: {
/**
@@ -165,7 +167,7 @@ export default {
<gl-link :href="commitUrl" class="commit-sha mr-0"> {{ shortSha }} </gl-link>
<div class="commit-title flex-truncate-parent">
- <span v-if="title" class="flex-truncate-child">
+ <tooltip-on-truncate v-if="title" class="flex-truncate-child" :title="title">
<user-avatar-link
v-if="hasAuthor"
:link-href="author.path"
@@ -174,8 +176,10 @@ export default {
:tooltip-text="author.username"
class="avatar-image-container"
/>
- <gl-link :href="commitUrl" class="commit-row-message cgray"> {{ title }} </gl-link>
- </span>
+ <gl-link :href="commitUrl" class="commit-row-message cgray">
+ {{ title }}
+ </gl-link>
+ </tooltip-on-truncate>
<span v-else> Can't find HEAD commit for this branch </span>
</div>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/table_pagination.vue b/app/assets/javascripts/vue_shared/components/pagination/table_pagination.vue
index 1e2d4ffa7e3..1e2d4ffa7e3 100644
--- a/app/assets/javascripts/vue_shared/components/table_pagination.vue
+++ b/app/assets/javascripts/vue_shared/components/pagination/table_pagination.vue
diff --git a/app/assets/stylesheets/page_bundles/ide.scss b/app/assets/stylesheets/page_bundles/ide.scss
index f08fa80495d..cbcd8a474f1 100644
--- a/app/assets/stylesheets/page_bundles/ide.scss
+++ b/app/assets/stylesheets/page_bundles/ide.scss
@@ -396,10 +396,6 @@ $ide-commit-header-height: 48px;
font-size: inherit;
}
- > div + div {
- padding-left: $gl-padding;
- }
-
svg {
vertical-align: sub;
}
@@ -410,13 +406,14 @@ $ide-commit-header-height: 48px;
}
}
+.ide-status-list {
+ > div + div {
+ padding-left: $gl-padding;
+ }
+}
+
.ide-status-file {
text-align: right;
-
- .ide-status-branch + &,
- &:first-child {
- margin-left: auto;
- }
}
// Not great, but this is to deal with our current output
.multi-file-preview-holder {
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index d5bc723aa8c..57b976b9121 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -2,7 +2,9 @@
class Admin::ApplicationSettingsController < Admin::ApplicationController
include InternalRedirect
+
before_action :set_application_setting
+ before_action :whitelist_query_limiting, only: [:usage_data]
def show
end
@@ -102,6 +104,10 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
@application_setting = Gitlab::CurrentSettings.current_application_settings
end
+ def whitelist_query_limiting
+ Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/63107')
+ end
+
def application_setting_params
params[:application_setting] ||= {}
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index a3ceb76845e..9e7e3ed5afb 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -273,9 +273,15 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
@merge_request.update(merge_error: nil, squash: merge_params.fetch(:squash, false))
if auto_merge_requested?
- AutoMergeService.new(project, current_user, merge_params)
- .execute(merge_request,
- params[:auto_merge_strategy] || AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
+ if merge_request.auto_merge_enabled?
+ # TODO: We should have a dedicated endpoint for updating merge params.
+ # See https://gitlab.com/gitlab-org/gitlab-ce/issues/63130.
+ AutoMergeService.new(project, current_user, merge_params).update(merge_request)
+ else
+ AutoMergeService.new(project, current_user, merge_params)
+ .execute(merge_request,
+ params[:auto_merge_strategy] || AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
+ end
else
@merge_request.merge_async(current_user.id, merge_params)
diff --git a/app/graphql/types/tree/blob_type.rb b/app/graphql/types/tree/blob_type.rb
index ba191b59132..760781f3612 100644
--- a/app/graphql/types/tree/blob_type.rb
+++ b/app/graphql/types/tree/blob_type.rb
@@ -10,7 +10,7 @@ module Types
field :web_url, GraphQL::STRING_TYPE, null: true
field :lfs_oid, GraphQL::STRING_TYPE, null: true, resolve: -> (blob, args, ctx) do
- Gitlab::Graphql::Loaders::BatchCommitLoader.new(blob.repository, blob.id).find
+ Gitlab::Graphql::Loaders::BatchLfsOidLoader.new(blob.repository, blob.id).find
end
end
end
diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb
index 8002eb08ada..855b243cc8a 100644
--- a/app/helpers/environments_helper.rb
+++ b/app/helpers/environments_helper.rb
@@ -26,6 +26,7 @@ module EnvironmentsHelper
"empty-no-data-svg-path" => image_path('illustrations/monitoring/no_data.svg'),
"empty-unable-to-connect-svg-path" => image_path('illustrations/monitoring/unable_to_connect.svg'),
"metrics-endpoint" => additional_metrics_project_environment_path(project, environment, format: :json),
+ "dashboard-endpoint" => metrics_dashboard_project_environment_path(project, environment, format: :json),
"deployment-endpoint" => project_environment_deployments_path(project, environment, format: :json),
"environments-endpoint": project_environments_path(project, format: :json),
"project-path" => project_path(project),
diff --git a/app/models/notification_recipient.rb b/app/models/notification_recipient.rb
index 9b2bbb7eba5..a7f73c0f29c 100644
--- a/app/models/notification_recipient.rb
+++ b/app/models/notification_recipient.rb
@@ -101,6 +101,7 @@ class NotificationRecipient
end
def excluded_watcher_action?
+ return false unless @type == :watch
return false unless @custom_action
NotificationSetting::EXCLUDED_WATCHER_EVENTS.include?(@custom_action)
@@ -140,7 +141,7 @@ class NotificationRecipient
return project_setting unless project_setting.nil? || project_setting.global?
- group_setting = closest_non_global_group_notification_settting
+ group_setting = closest_non_global_group_notification_setting
return group_setting unless group_setting.nil?
@@ -148,7 +149,7 @@ class NotificationRecipient
end
# Returns the notification_setting of the lowest group in hierarchy with non global level
- def closest_non_global_group_notification_settting
+ def closest_non_global_group_notification_setting
return unless @group
@group
diff --git a/app/models/project.rb b/app/models/project.rb
index e64a4b313aa..9d17d68eee2 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -311,7 +311,7 @@ class Project < ApplicationRecord
delegate :root_ancestor, to: :namespace, allow_nil: true
delegate :last_pipeline, to: :commit, allow_nil: true
delegate :external_dashboard_url, to: :metrics_setting, allow_nil: true, prefix: true
- delegate :default_git_depth, :default_git_depth=, to: :ci_cd_settings
+ delegate :default_git_depth, :default_git_depth=, to: :ci_cd_settings, prefix: :ci
# Validations
validates :creator, presence: true, on: :create
diff --git a/app/presenters/ci/build_runner_presenter.rb b/app/presenters/ci/build_runner_presenter.rb
index c75f62149f8..b928988ed8c 100644
--- a/app/presenters/ci/build_runner_presenter.rb
+++ b/app/presenters/ci/build_runner_presenter.rb
@@ -28,7 +28,7 @@ module Ci
if git_depth_variable
git_depth_variable[:value]
elsif Feature.enabled?(:ci_project_git_depth, default_enabled: true)
- project.default_git_depth
+ project.ci_default_git_depth
end.to_i
end
diff --git a/app/services/auto_merge/base_service.rb b/app/services/auto_merge/base_service.rb
index 7f0a41b3dfa..d726085b89a 100644
--- a/app/services/auto_merge/base_service.rb
+++ b/app/services/auto_merge/base_service.rb
@@ -20,6 +20,14 @@ module AutoMerge
strategy.to_sym
end
+ def update(merge_request)
+ merge_request.merge_params.merge!(params)
+
+ return :failed unless merge_request.save
+
+ strategy.to_sym
+ end
+
def cancel(merge_request)
if cancel_auto_merge(merge_request)
yield if block_given?
diff --git a/app/services/auto_merge_service.rb b/app/services/auto_merge_service.rb
index a3a780ff388..926d2f5fc66 100644
--- a/app/services/auto_merge_service.rb
+++ b/app/services/auto_merge_service.rb
@@ -24,6 +24,12 @@ class AutoMergeService < BaseService
service.execute(merge_request)
end
+ def update(merge_request)
+ return :failed unless merge_request.auto_merge_enabled?
+
+ get_service_instance(merge_request.auto_merge_strategy).update(merge_request)
+ end
+
def process(merge_request)
return unless merge_request.auto_merge_enabled?
diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb
index 0b4ab7b8e4d..d8fa9d37359 100644
--- a/app/services/projects/fork_service.rb
+++ b/app/services/projects/fork_service.rb
@@ -43,10 +43,10 @@ module Projects
shared_runners_enabled: @project.shared_runners_enabled,
namespace_id: target_namespace.id,
fork_network: fork_network,
- # We need to set default_git_depth to 0 for the forked project when
- # @project.default_git_depth is nil in order to keep the same behaviour
+ # We need to set ci_default_git_depth to 0 for the forked project when
+ # @project.ci_default_git_depth is nil in order to keep the same behaviour
# and not get ProjectCiCdSetting::DEFAULT_GIT_DEPTH set on create
- ci_cd_settings_attributes: { default_git_depth: @project.default_git_depth || 0 },
+ ci_cd_settings_attributes: { default_git_depth: @project.ci_default_git_depth || 0 },
# We need to assign the fork network membership after the project has
# been instantiated to avoid ActiveRecord trying to create it when
# initializing the project, as that would cause a foreign key constraint
diff --git a/app/views/admin/application_settings/_visibility_and_access.html.haml b/app/views/admin/application_settings/_visibility_and_access.html.haml
index 03ef2924617..c07bafbe302 100644
--- a/app/views/admin/application_settings/_visibility_and_access.html.haml
+++ b/app/views/admin/application_settings/_visibility_and_access.html.haml
@@ -8,6 +8,7 @@
.form-group
= f.label s_('ProjectCreationLevel|Default project creation protection'), class: 'label-bold'
= f.select :default_project_creation, options_for_select(Gitlab::Access.project_creation_options, @application_setting.default_project_creation), {}, class: 'form-control'
+ = render_if_exists 'admin/application_settings/default_project_deletion_protection_setting', form: f
.form-group.visibility-level-setting
= f.label :default_project_visibility, class: 'label-bold'
= render('shared/visibility_radios', model_method: :default_project_visibility, form: f, selected_level: @application_setting.default_project_visibility, form_model: Project.new)
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index 1074cd6bf4e..a5eaae2dff4 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -22,7 +22,7 @@
%span.badge.badge-success.prepend-left-5
= s_('Branches|protected')
- = render_if_exists 'projects/branches/diverged_from_upstream'
+ = render_if_exists 'projects/branches/diverged_from_upstream', branch: branch
.block-truncated
- if commit
diff --git a/changelogs/archive.md b/changelogs/archive.md
index dd7c21dabd6..e36e859a351 100644
--- a/changelogs/archive.md
+++ b/changelogs/archive.md
@@ -274,7 +274,7 @@
- Pass variables from deployment project services to CI runner. !8107
- New Gitea importer. !8116
- Introduce "Set up autodeploy" button to help configure GitLab CI for deployment. !8135
-- Prevent enviroment table to overflow when name has underscores. !8142
+- Prevent environment table to overflow when name has underscores. !8142
- Fix missing service error importing from EE to CE. !8144
- Milestoneish SQL performance partially improved and memoized. !8146
- Allow unauthenticated access to Repositories API GET endpoints. !8148
@@ -562,7 +562,7 @@
- Fix broken issue/merge request links in JIRA comments. !6143 (Brian Kintz)
- Fix filtering of milestones with quotes in title (airatshigapov)
- Fix issue boards dragging bug in Safari
-- Refactor less readable existance checking code from CoffeeScript !6289 (jlogandavison)
+- Refactor less readable existence checking code from CoffeeScript !6289 (jlogandavison)
- Update mail_room and enable sentinel support to Reply By Email (!7101)
- Add task completion status in Issues and Merge Requests tabs: "X of Y tasks completed" (!6527, @gmesalazar)
- Simpler arguments passed to named_route on toggle_award_url helper method
@@ -956,7 +956,7 @@
## 8.12.0 (2016-09-22)
- - Removes inconsistency regarding tagging immediatelly as merged once you create a new branch. !6408
+ - Removes inconsistency regarding tagging immediately as merged once you create a new branch. !6408
- Update the rouge gem to 2.0.6, which adds highlighting support for JSX, Prometheus, and others. !6251
- Only check :can_resolve permission if the note is resolvable
- Bump fog-aws to v0.11.0 to support ap-south-1 region
@@ -1389,7 +1389,7 @@
- Fix notification_service argument error of declined invitation emails
- Fix a memory leak caused by Banzai::Filter::SanitizationFilter
- Speed up todos queries by limiting the projects set we join with
- - Ensure file editing in UI does not overwrite commited changes without warning user
+ - Ensure file editing in UI does not overwrite committed changes without warning user
- Eliminate unneeded calls to Repository#blob_at when listing commits with no path
- Update gitlab_git gem to 10.4.7
- Simplify SQL queries of marking a todo as done
@@ -2076,7 +2076,7 @@
- Don't show forks button when user can't view forks
- Fix atom feed links and rendering
- Files over 5MB can only be viewed in their raw form, files over 1MB without highlighting !3718
- - Add support for supressing text diffs using .gitattributes on the default branch (Matt Oakes)
+ - Add support for suppressing text diffs using .gitattributes on the default branch (Matt Oakes)
- Add eager load paths to help prevent dependency load issues in Sidekiq workers. !3724
- Added multiple colors for labels in dropdowns when dups happen.
- Show commits in the same order as `git log`
@@ -2194,7 +2194,7 @@
- All images in discussions and wikis now link to their source files !3464 (Connor Shea).
- Return status code 303 after a branch DELETE operation to avoid project deletion (Stan Hu)
- Add setting for customizing the list of trusted proxies !3524
- - Allow projects to be transfered to a lower visibility level group
+ - Allow projects to be transferred to a lower visibility level group
- Fix `signed_in_ip` being set to 127.0.0.1 when using a reverse proxy !3524
- Improved Markdown rendering performance !3389
- Make shared runners text in box configurable
@@ -2209,7 +2209,7 @@
- API: Ability to update a group (Robert Schilling)
- API: Ability to move issues (Robert Schilling)
- Fix Error 500 after renaming a project path (Stan Hu)
- - Fix a bug whith trailing slash in teamcity_url (Charles May)
+ - Fix a bug with trailing slash in teamcity_url (Charles May)
- Allow back dating on issues when created or updated through the API
- Allow back dating on issue notes when created through the API
- Propose license template when creating a new LICENSE file
@@ -2219,7 +2219,7 @@
- Allow SAML to handle external users based on user's information !3530
- Allow Omniauth providers to be marked as `external` !3657
- Add endpoints to archive or unarchive a project !3372
- - Fix a bug whith trailing slash in bamboo_url
+ - Fix a bug with trailing slash in bamboo_url
- Add links to CI setup documentation from project settings and builds pages
- Display project members page to all members
- Handle nil descriptions in Slack issue messages (Stan Hu)
@@ -2610,7 +2610,7 @@
- Fixed logo animation on Safari (Roman Rott)
- Fix Merge When Succeeded when multiple stages
- Hide remove source branch button when the MR is merged but new commits are pushed (Zeger-Jan van de Weg)
- - In seach autocomplete show only groups and projects you are member of
+ - In search autocomplete show only groups and projects you are member of
- Don't process cross-reference notes from forks
- Fix: init.d script not working on OS X
- Faster snippet search
@@ -2870,7 +2870,7 @@
- Bump Redis requirement to 2.8 for Sidekiq 4 (Stan Hu)
- Fix: Assignee selector is empty when 'Unassigned' is selected (Jose Corcuera)
- WIP identifier on merge requests no longer requires trailing space
- - Add rake tasks for git repository maintainance (Zeger-Jan van de Weg)
+ - Add rake tasks for git repository maintenance (Zeger-Jan van de Weg)
- Fix 500 error when update group member permission
- Fix: As an admin, cannot add oneself as a member to a group/project
- Trim leading and trailing whitespace of milestone and issueable titles (Jose Corcuera)
@@ -3199,7 +3199,7 @@
- Sort issues by creation date in Bitbucket importer (Stan Hu)
- Prevent too many redirects upon login when home page URL is set to external_url (Stan Hu)
- Improve dropdown positioning on the project home page (Hannes Rosenögger)
- - Upgrade browser gem to 1.0.0 to avoid warning in IE11 compatibilty mode (Stan Hu)
+ - Upgrade browser gem to 1.0.0 to avoid warning in IE11 compatibility mode (Stan Hu)
- Remove user OAuth tokens from the database and request new tokens each session (Stan Hu)
- Restrict users API endpoints to use integer IDs (Stan Hu)
- Only show recent push event if the branch still exists or a recent merge request has not been created (Stan Hu)
@@ -3209,7 +3209,7 @@
- Ability to fetch merge requests from refs/merge-requests/:id
- Allow displaying of archived projects in the admin interface (Artem Sidorenko)
- Allow configuration of import sources for new projects (Artem Sidorenko)
- - Search for comments should be case insensetive
+ - Search for comments should be case insensitive
- Create cross-reference for closing references on commits pushed to non-default branches (Maël Valais)
- Ability to search milestones
- Gracefully handle SMTP user input errors (e.g. incorrect email addresses) to prevent Sidekiq retries (Stan Hu)
@@ -3477,7 +3477,7 @@
- Update Asciidoctor gem to version 1.5.2. (Jakub Jirutka)
- Fix resolving of relative links to repository files in AsciiDoc documents. (Jakub Jirutka)
- Use the user list from the target project in a merge request (Stan Hu)
-- Default extention for wiki pages is now .md instead of .markdown (Jeroen van Baarsen)
+- Default extension for wiki pages is now .md instead of .markdown (Jeroen van Baarsen)
- Add validation to wiki page creation (only [a-zA-Z0-9/_-] are allowed) (Jeroen van Baarsen)
- Fix new/empty milestones showing 100% completion value (Jonah Bishop)
- Add a note when an Issue or Merge Request's title changes
@@ -3613,7 +3613,7 @@
- Set EmailsOnPush reply-to address to committer email when enabled.
- Fix broken file browsing with a submodule that contains a relative link (Stan Hu)
- Fix persistent XSS vulnerability around profile website URLs.
-- Fix project import URL regex to prevent arbitary local repos from being imported.
+- Fix project import URL regex to prevent arbitrary local repos from being imported.
- Fix directory traversal vulnerability around uploads routes.
- Fix directory traversal vulnerability around help pages.
- Don't leak existence of project via search autocomplete.
@@ -3676,7 +3676,7 @@
- Don't show commit comment button when user is not signed in.
- Fix admin user projects lists.
- Don't leak private group existence by redirecting from namespace controller to group controller.
-- Ability to skip some items from backup (database, respositories or uploads)
+- Ability to skip some items from backup (database, repositories or uploads)
- Archive repositories in background worker.
- Import GitHub, Bitbucket or GitLab.com projects owned by authenticated user into current namespace.
- Project labels are now available over the API under the "tag_list" field (Cristian Medina)
@@ -3701,7 +3701,7 @@
## 7.9.4
-- Security: Fix project import URL regex to prevent arbitary local repos from being imported
+- Security: Fix project import URL regex to prevent arbitrary local repos from being imported
- Fixed issue where only 25 commits would load in file listings
- Fix LDAP identities after config update
@@ -4199,7 +4199,7 @@
- Only masters can rewrite/remove git tags
- Add X-Frame-Options SAMEORIGIN to Nginx config so Sidekiq admin is visible
- UI improvements
-- Case-insensetive search for issues
+- Case-insensitive search for issues
- Update to rails 4.1
- Improve performance of application for projects and groups with a lot of members
- Formally support Ruby 2.1
@@ -4358,7 +4358,7 @@
- Group avatar
- Pygments.rb replaced with highlight.js
- Improve Merge request diff store logic
-- Improve render performnace for MR show page
+- Improve render performances for MR show page
- Fixed Assembla hardcoded project name
- Jira integration documentation
- Refactored app/services
diff --git a/changelogs/unreleased/5615-non-admins-only-archieve-ce.yml b/changelogs/unreleased/5615-non-admins-only-archieve-ce.yml
new file mode 100644
index 00000000000..ac1aa249b82
--- /dev/null
+++ b/changelogs/unreleased/5615-non-admins-only-archieve-ce.yml
@@ -0,0 +1,5 @@
+---
+title: Add deletion protection setting column to application_settings table
+merge_request: 29268
+author:
+type: other
diff --git a/changelogs/unreleased/58433-email-notifications-do-not-work-properly-issue-due-date.yml b/changelogs/unreleased/58433-email-notifications-do-not-work-properly-issue-due-date.yml
new file mode 100644
index 00000000000..4579721446a
--- /dev/null
+++ b/changelogs/unreleased/58433-email-notifications-do-not-work-properly-issue-due-date.yml
@@ -0,0 +1,5 @@
+---
+title: Fix email notifications for user excluded actions
+merge_request: 28835
+author:
+type: fixed
diff --git a/changelogs/unreleased/58984-doc-missing-milestones-and-labels-links.yml b/changelogs/unreleased/58984-doc-missing-milestones-and-labels-links.yml
new file mode 100644
index 00000000000..6b74303c16e
--- /dev/null
+++ b/changelogs/unreleased/58984-doc-missing-milestones-and-labels-links.yml
@@ -0,0 +1,5 @@
+---
+title: Document when milestones and labels links are missing
+merge_request: 29355
+author:
+type: other
diff --git a/changelogs/unreleased/59651-remove-unnecessary-decimal-places-on-chart-axes.yml b/changelogs/unreleased/59651-remove-unnecessary-decimal-places-on-chart-axes.yml
new file mode 100644
index 00000000000..fea34099135
--- /dev/null
+++ b/changelogs/unreleased/59651-remove-unnecessary-decimal-places-on-chart-axes.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unnecessary decimals on Metrics chart axis
+merge_request: 29468
+author:
+type: fixed
diff --git a/changelogs/unreleased/62300-target-area-for-dropdown-list-items-is-too-small-on-metrics-dashboard.yml b/changelogs/unreleased/62300-target-area-for-dropdown-list-items-is-too-small-on-metrics-dashboard.yml
new file mode 100644
index 00000000000..7944e6faa27
--- /dev/null
+++ b/changelogs/unreleased/62300-target-area-for-dropdown-list-items-is-too-small-on-metrics-dashboard.yml
@@ -0,0 +1,5 @@
+---
+title: Enlarge metrics time-window dropdown links
+merge_request: 29458
+author:
+type: fixed
diff --git a/changelogs/unreleased/62788-clean-up-pagination.yml b/changelogs/unreleased/62788-clean-up-pagination.yml
new file mode 100644
index 00000000000..05e3a4527b8
--- /dev/null
+++ b/changelogs/unreleased/62788-clean-up-pagination.yml
@@ -0,0 +1,5 @@
+---
+title: Moves the table pagination shared component
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/9186-implement-atmtwps-state-to-mr-widget.yml b/changelogs/unreleased/9186-implement-atmtwps-state-to-mr-widget.yml
new file mode 100644
index 00000000000..2c1d56f197e
--- /dev/null
+++ b/changelogs/unreleased/9186-implement-atmtwps-state-to-mr-widget.yml
@@ -0,0 +1,5 @@
+---
+title: Update the merge request widget's "Merge" button to support merge trains
+merge_request: 27594
+author:
+type: added
diff --git a/changelogs/unreleased/expose-project-git-depth-via-api.yml b/changelogs/unreleased/expose-project-git-depth-via-api.yml
new file mode 100644
index 00000000000..e9d158fda16
--- /dev/null
+++ b/changelogs/unreleased/expose-project-git-depth-via-api.yml
@@ -0,0 +1,5 @@
+---
+title: Get and edit ci_default_git_depth via project API
+merge_request: 29353
+author:
+type: added
diff --git a/changelogs/unreleased/fix-diverged-branch-locals.yml b/changelogs/unreleased/fix-diverged-branch-locals.yml
new file mode 100644
index 00000000000..719d669fad3
--- /dev/null
+++ b/changelogs/unreleased/fix-diverged-branch-locals.yml
@@ -0,0 +1,5 @@
+---
+title: Fix diverged branch locals
+merge_request: 29508
+author:
+type: fixed
diff --git a/changelogs/unreleased/patch-65.yml b/changelogs/unreleased/patch-65.yml
new file mode 100644
index 00000000000..9ce628a6541
--- /dev/null
+++ b/changelogs/unreleased/patch-65.yml
@@ -0,0 +1,5 @@
+---
+title: Show tooltip on truncated commit title
+merge_request: 28865
+author: Timofey Trofimov
+type: other
diff --git a/changelogs/unreleased/upgrade-pages-to-v1-6-1.yml b/changelogs/unreleased/upgrade-pages-to-v1-6-1.yml
new file mode 100644
index 00000000000..0ab58bb50d8
--- /dev/null
+++ b/changelogs/unreleased/upgrade-pages-to-v1-6-1.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Pages to v1.6.1
+merge_request: 29559
+author:
+type: other
diff --git a/config/initializers/rack_timeout.rb b/config/initializers/rack_timeout.rb
index 5c4f2dd708c..58f46b55725 100644
--- a/config/initializers/rack_timeout.rb
+++ b/config/initializers/rack_timeout.rb
@@ -18,6 +18,6 @@ if defined?(::Puma) && !Rails.env.test?
wait_timeout: 90)
end
- observer = Gitlab::RackTimeoutObserver.new
+ observer = Gitlab::Cluster::RackTimeoutObserver.new
Rack::Timeout.register_state_change_observer(:gitlab_rack_timeout, &observer.callback)
end
diff --git a/db/migrate/20190605104727_add_default_project_deletion_protection_to_application_settings.rb b/db/migrate/20190605104727_add_default_project_deletion_protection_to_application_settings.rb
new file mode 100644
index 00000000000..ee04b49813b
--- /dev/null
+++ b/db/migrate/20190605104727_add_default_project_deletion_protection_to_application_settings.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddDefaultProjectDeletionProtectionToApplicationSettings < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default :application_settings, :default_project_deletion_protection, :boolean, default: false, allow_null: false
+ end
+
+ def down
+ remove_column :application_settings, :default_project_deletion_protection
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 1755730bb72..c57a73c66da 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -194,6 +194,7 @@ ActiveRecord::Schema.define(version: 20190611161641) do
t.text "encrypted_lets_encrypt_private_key"
t.text "encrypted_lets_encrypt_private_key_iv"
t.boolean "dns_rebinding_protection_enabled", default: true, null: false
+ t.boolean "default_project_deletion_protection", default: false, null: false
t.index ["usage_stats_set_by_user_id"], name: "index_application_settings_on_usage_stats_set_by_user_id", using: :btree
end
diff --git a/doc/administration/repository_storage_types.md b/doc/administration/repository_storage_types.md
index 4db3cbb9958..38842693d73 100644
--- a/doc/administration/repository_storage_types.md
+++ b/doc/administration/repository_storage_types.md
@@ -106,6 +106,11 @@ enabled for individual projects by executing
be on hashed storage, should not be a fork itself, and hashed storage should be
enabled for all new projects.
+DANGER: **Danger:**
+Do not run `git prune` or `git gc` in pool repositories! This can
+cause data loss in "real" repositories that depend on the pool in
+question.
+
### How to migrate to Hashed Storage
To start a migration, enable Hashed Storage for new projects:
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 75669d85803..1d58e390d9e 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -143,6 +143,7 @@ When the user is authenticated and `simple` is not set this returns something li
"forks_count": 0,
"star_count": 0,
"runners_token": "b8547b1dc37721d05889db52fa2f02",
+ "ci_default_git_depth": 50,
"public_jobs": true,
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
@@ -225,6 +226,7 @@ When the user is authenticated and `simple` is not set this returns something li
"forks_count": 0,
"star_count": 0,
"runners_token": "b8547b1dc37721d05889db52fa2f02",
+ "ci_default_git_depth": 0,
"public_jobs": true,
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
@@ -334,6 +336,7 @@ GET /users/:user_id/projects
"forks_count": 0,
"star_count": 0,
"runners_token": "b8547b1dc37721d05889db52fa2f02",
+ "ci_default_git_depth": 50,
"public_jobs": true,
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
@@ -416,6 +419,7 @@ GET /users/:user_id/projects
"forks_count": 0,
"star_count": 0,
"runners_token": "b8547b1dc37721d05889db52fa2f02",
+ "ci_default_git_depth": 0,
"public_jobs": true,
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
@@ -528,6 +532,7 @@ GET /projects/:id
"forks_count": 0,
"star_count": 0,
"runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
+ "ci_default_git_depth": 50,
"public_jobs": true,
"shared_with_groups": [
{
@@ -763,6 +768,7 @@ PUT /projects/:id
| `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project |
| `avatar` | mixed | no | Image file for avatar of the project |
| `ci_config_path` | string | no | The path to CI config file |
+| `ci_default_git_depth` | integer | no | Default number of revisions for [shallow cloning](../user/project/pipelines/settings.md#git-shallow-clone) |
## Fork project
@@ -1160,6 +1166,7 @@ Example response:
"forks_count": 0,
"star_count": 0,
"runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
+ "ci_default_git_depth": 50,
"public_jobs": true,
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
@@ -1264,6 +1271,7 @@ Example response:
"forks_count": 0,
"star_count": 0,
"runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
+ "ci_default_git_depth": 50,
"public_jobs": true,
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index d8068bbb7f0..b4c4bea6447 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -90,7 +90,7 @@ The second approach is to use the special docker-in-docker (dind)
(`docker`) and run the job script in context of that
image in privileged mode.
-NOTE: **Note:** `docker-compose` is not part of docker-in-docker (dind). In case you'd like to use `docker-compose` in your CI builds, please follow the (installation instructions for docker-compose)[https://docs.docker.com/compose/install/] provided by docker.
+NOTE: **Note:** `docker-compose` is not part of docker-in-docker (dind). In case you'd like to use `docker-compose` in your CI builds, please follow the [installation instructions for docker-compose](https://docs.docker.com/compose/install/) provided by docker.
In order to do that, follow the steps:
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index d09efce7cc1..29578efacbb 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -466,6 +466,29 @@ that runner.
> - If the repository is private you need to authenticate your GitLab Runner in the
> registry. Learn more about how [GitLab Runner works in this case][runner-priv-reg].
+To access private container registries, the GitLab Runner process can use:
+
+- [Statically defined credentials](#using-statically-defined-credentials). That is, a username and password for a specific registry.
+- [Credentials Store](#using-credentials-store). For more information, see [the relevant Docker documentation](https://docs.docker.com/engine/reference/commandline/login/#credentials-store).
+- [Credential Helpers](#using-credential-helpers). For more information, see [the relevant Docker documentation](https://docs.docker.com/engine/reference/commandline/login/#credential-helpers).
+
+To define which should be used, the GitLab Runner process reads the configuration in the following order:
+
+- `DOCKER_AUTH_CONFIG` variable provided as either:
+ - A [variable](../variables/README.md#gitlab-cicd-environment-variables) in `.gitlab-ci.yml`.
+ - A project's variables stored on the projects **Settings > CI/CD** page.
+- `DOCKER_AUTH_CONFIG` variable provided as environment variable in `config.toml` of the Runner.
+- `config.json` file placed in `$HOME/docker` directory of the user running GitLab Runner process.
+ If the `--user` flag is provided to run the GitLab Runner child processes as unprivileged user,
+ the home directory of the main GitLab Runner process user will be used.
+
+NOTE: **Note:**
+GitLab Runner reads this configuration **only** from `config.toml` and ignores it if
+it's provided as an environment variable. This is because GitLab Runnner uses **only**
+`config.toml` configuration and doesn't interpolate **ANY** environment variables at
+runtime.
+
+### Using statically-defined credentials
As an example, let's assume that you want to use the `registry.example.com:5000/private/image:latest`
image which is private and requires you to login into a private container registry.
@@ -543,6 +566,78 @@ for the Runner to match the `DOCKER_AUTH_CONFIG`. For example, if
then the `DOCKER_AUTH_CONFIG` must also specify `registry.example.com:5000`.
Specifying only `registry.example.com` will not work.
+
+### Using Credentials Store
+
+> Support for using Credentials Store was added in GitLab Runner 9.5.
+
+To configure credentials store, follow these steps:
+
+1. To use a credentials store, you need an external helper program to interact with a specific keychain or external store.
+Make sure helper program is available in GitLab Runner `$PATH`.
+
+1. Make GitLab Runner use it. There are two ways to accomplish this. Either:
+ - Create a
+ [variable](../variables/README.md#gitlab-cicd-environment-variables)
+ `DOCKER_AUTH_CONFIG` with the content of the
+ Docker configuration file as the value:
+
+ ```json
+ {
+ "credsStore": "osxkeychain"
+ }
+ ```
+
+ - Or, if you are running self-hosted Runners, add the above JSON to
+ `${GITLAB_RUNNER_HOME}/.docker/config.json`. GitLab Runner will read this config file
+ and will use the needed helper for this specific repository.
+
+NOTE: **Note:** `credsStore` is used to access ALL the registries.
+If you will want to use both images from private registry and public images from DockerHub,
+pulling from DockerHub will fail, because Docker daemon will try to use the same credentials for **ALL** the registries.
+
+### Using Credential Helpers
+
+> Support for using Credential Helpers was added in GitLab Runner 12.0
+
+As an example, let's assume that you want to use the `aws_account_id.dkr.ecr.region.amazonaws.com/private/image:latest`
+image which is private and requires you to log in into a private container registry.
+
+To configure access for `aws_account_id.dkr.ecr.region.amazonaws.com`, follow these steps:
+
+1. Make sure `docker-credential-ecr-login` is available in GitLab Runner's `$PATH`.
+
+1. Make GitLab Runner use it. There are two ways to accomplish this. Either:
+ - Create a [variable](../variables/README.md#gitlab-cicd-environment-variables)
+ `DOCKER_AUTH_CONFIG` with the content of the
+ Docker configuration file as the value:
+
+ ```json
+ {
+ "credHelpers": {
+ "aws_account_id.dkr.ecr.region.amazonaws.com": "ecr-login"
+ }
+ }
+ ```
+
+ - Or, if you are running self-hosted Runners,
+ add the above JSON to `${GITLAB_RUNNER_HOME}/.docker/config.json`.
+ GitLab Runner will read this config file and will use the needed helper for this
+ specific repository.
+
+1. You can now use any private image from `aws_account_id.dkr.ecr.region.amazonaws.com` defined in
+ `image` and/or `services` in your `.gitlab-ci.yml` file:
+
+ ```yaml
+ image: aws_account_id.dkr.ecr.region.amazonaws.com/private/image:latest
+ ```
+
+ In the example above, GitLab Runner will look at `aws_account_id.dkr.ecr.region.amazonaws.com` for the
+ image `private/image:latest`.
+
+You can add configuration for as many registries as you want, adding more
+registries to the `"credHelpers"` hash as described above.
+
## Configuring services
Many services accept environment variables which allow you to easily change
diff --git a/doc/ci/examples/README.md b/doc/ci/examples/README.md
index d2ea30839a4..1548b0e619f 100644
--- a/doc/ci/examples/README.md
+++ b/doc/ci/examples/README.md
@@ -62,8 +62,8 @@ For examples of setting up GitLab CI/CD for cloud-based environments, see:
- [Automating Kubernetes Deployments with GitLab CI/CD](https://www.youtube.com/watch?v=wEDRfAz6_Uw)
- [How to autoscale continuous deployment with GitLab Runner on DigitalOcean](https://about.gitlab.com/2018/06/19/autoscale-continuous-deployment-gitlab-runner-digital-ocean/)
- [How to create a CI/CD pipeline with Auto Deploy to Kubernetes using GitLab and Helm](https://about.gitlab.com/2017/09/21/how-to-create-ci-cd-pipeline-with-autodeploy-to-kubernetes-using-gitlab-and-helm/)
+- [Demo - Deploying from GitLab to OpenShift Container Cluster](https://youtu.be/EwbhA53Jpp4)
-<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
See also the following video overviews:
- [Containers, Schedulers, and GitLab CI](https://www.youtube.com/watch?v=d-9awBxEbvQ).
@@ -100,6 +100,10 @@ For examples of others who have implemented GitLab CI/CD, see:
- [Fast and natural continuous integration with GitLab CI](https://about.gitlab.com/2017/05/22/fast-and-natural-continuous-integration-with-gitlab-ci/)
- [Demo: CI/CD with GitLab in action](https://about.gitlab.com/2017/03/13/ci-cd-demo/)
+### Migrating to GitLab from third-party CI tools
+
+- [Migrating from Jenkins to GitLab](https://youtu.be/RlEVGOpYF5Y)
+
### Integrating GitLab CI/CD with other systems
To see how you can integrate GitLab CI/CD with third-party systems, see:
diff --git a/doc/ci/metrics_reports.md b/doc/ci/metrics_reports.md
index b7824402d45..3ded6673149 100644
--- a/doc/ci/metrics_reports.md
+++ b/doc/ci/metrics_reports.md
@@ -28,6 +28,11 @@ Consider the following examples of data that can utilize Metrics Reports:
Metrics are read from the metrics report (default: `metrics.txt`). They are parsed and displayed in the MR widget.
+All values are considered strings and string compare is used to find differences between the latest available `metrics` artifact from:
+
+- `master`
+- The feature branch
+
## How to set it up
Add a job that creates a [metrics report](yaml/README.md#artifactsreportsmetrics-premium) (default filename: `metrics.txt`). The file should conform to the [OpenMetrics](https://openmetrics.io/) format.
diff --git a/doc/development/git_object_deduplication.md b/doc/development/git_object_deduplication.md
index 81c5f69c7b8..b512d7611d3 100644
--- a/doc/development/git_object_deduplication.md
+++ b/doc/development/git_object_deduplication.md
@@ -10,10 +10,10 @@ GitLab implements Git object deduplication.
## Enabling Git object deduplication via feature flags
-As of GitLab 11.9, Git object deduplication in GitLab is in beta. In this
-document, you can read about the caveats of enabling the feature. Also,
-note that Git object deduplication is limited to forks of public
-projects on hashed repository storage.
+As of GitLab 12.0, Git object deduplication in GitLab is still behind a
+feature flag. In this document, you can read about the effects of
+enabling the feature. Also, note that Git object deduplication is
+limited to forks of public projects on hashed repository storage.
You can enable deduplication globally by setting the `object_pools`
feature flag to `true`:
@@ -51,6 +51,15 @@ configuration. Objects in A that are not in B will remain in A. For this
to work, it is of course critical that **no objects ever get deleted from
B** because A might need them.
+DANGER: **Danger:**
+Do not run `git prune` or `git gc` in pool repositories! This can
+cause data loss in "real" repositories that depend on the pool in
+question.
+
+The danger lies in `git prune`, and `git gc` calls `git prune`. The
+problem is that `git prune`, when running in a pool repository, cannot
+reliable decide if an object is no longer needed.
+
### Git alternates in GitLab: pool repositories
GitLab organizes this object borrowing by creating special **pool
@@ -80,43 +89,10 @@ across a collection of GitLab project repositories at the Git level:
The effectiveness of Git object deduplication in GitLab depends on the
amount of overlap between the pool repository and each of its
-participants. As of GitLab 11.9, we have a somewhat optimistic system.
-The only data that will be deduplicated is the data in the source
-project repository at the time the pool repository is created. That is,
-the data in the source project at the time of the first fork *after* the
-deduplication feature has been enabled.
-
-When we enable the object deduplication feature for
-gitlab.com/gitlab-org/gitlab-ce, which is about 1GB at the time of
-writing, all new forks of that project would be 1GB smaller than they
-would have been without Git object deduplication. So even in its current
-optimistic form, we expect Git object deduplication in GitLab to make a
-difference.
-
-However, if a lot of Git objects get added to the project repositories
-in a pool after the pool repository was created these new Git objects
-will currently (GitLab 11.9) not get deduplicated. Over time, the
-deduplication factor of the pool will get worse and worse.
-
-As an extreme example, if we create an empty repository A, and fork that
-to repository B, behind the scenes we get an object pool P with no
-objects in it at all. If we then push 1GB of Git data to A, and push the
-same Git data to B, it will not get deduplicated, because that data was
-not in A at the time P was created.
-
-This also matters in less extreme examples. Consider a pool P with
-source project A and 500 active forks B1, B2,...,B500. Suppose,
-optimistically, that the forks are fully deduplicated at the start of
-our scenario. Now some time passes and 200MB of new Git data gets added
-to project A. Because of the forking workflow, this data makes also its way
-into the forks B1, ..., B500. That means we would now have 100GB of Git
-data sitting around (500 \* 200MB) across the forks, that could have
-been deduplicated. But because of the way we do deduplication this new
-data will not be deduplicated.
-
-> TODO Add periodic maintenance of object pools to prevent gradual loss
-> of deduplication over time.
-> https://gitlab.com/groups/gitlab-org/-/epics/524
+participants. Each time garbage collection runs on the source project,
+Git objects from the source project will get migrated to the pool
+repository. One by one, as garbage collection runs, other member
+projects will benefit from the new objects that got added to the pool.
## SQL model
@@ -136,6 +112,9 @@ are as follows:
- a `PoolRepository` has exactly one "source `Project`"
(`pool.source_project`)
+> TODO Fix invalid SQL data for pools created prior to GitLab 11.11
+> https://gitlab.com/gitlab-org/gitaly/issues/1653.
+
### Assumptions
- All repositories in a pool must use [hashed
@@ -146,10 +125,6 @@ are as follows:
The Git alternates mechanism relies on direct disk access across
multiple repositories, and we can only assume direct disk access to
be possible within a Gitaly storage shard.
-- All project repositories in a pool must have "Public" visibility in
- GitLab at the time they join. There are gotchas around visibility of
- Git objects across alternates links. This restriction is a defense
- against accidentally leaking private Git data.
- The only two ways to remove a member project from a pool are (1) to
delete the project or (2) to move the project to another Gitaly
storage shard.
@@ -187,17 +162,14 @@ are as follows:
### Consequences
- If a normal Project participating in a pool gets moved to another
- Gitaly storage shard, its "belongs to PoolRepository" relation must
+ Gitaly storage shard, its "belongs to PoolRepository" relation will
be broken. Because of the way moving repositories between shard is
implemented, we will automatically get a fresh self-contained copy
of the project's repository on the new storage shard.
- If the source project of a pool gets moved to another Gitaly storage
- shard or is deleted, we may have to break the "PoolRepository has
- one source Project" relation?
-
-> TODO What happens, or should happen, if a source project changes
-> visibility, is deleted, or moves to another storage shard?
-> https://gitlab.com/gitlab-org/gitaly/issues/1488
+ shard or is deleted the "source project" relation is not broken.
+ However, as of GitLab 12.0 a pool will not fetch from a source
+ unless the source is on the same Gitaly shard.
## Consistency between the SQL pool relation and Gitaly
@@ -209,16 +181,8 @@ repository and a pool.
### Pool existence
If GitLab thinks a pool repository exists (i.e. it exists according to
-SQL), but it does not on the Gitaly server, then certain RPC calls that
-take the object pool as an argument will fail.
-
-> TODO What happens if SQL says the pool repo exists but Gitaly says it
-> does not? https://gitlab.com/gitlab-org/gitaly/issues/1533
-
-If GitLab thinks a pool does not exist, while it does exist on disk,
-that has no direct consequences on its own. However, if other
-repositories on disk borrow objects from this unknown pool repository
-then we risk data loss, see below.
+SQL), but it does not on the Gitaly server, then it will be created on
+the fly by Gitaly.
### Pool relation existence
@@ -226,26 +190,19 @@ There are three different things that can go wrong here.
#### 1. SQL says repo A belongs to pool P but Gitaly says A has no alternate objects
-In this case, we miss out on disk space savings but all RPC's on A itself
-will function fine. As long as Git can find all its objects, it does not
-matter exactly where those objects are.
+In this case, we miss out on disk space savings but all RPC's on A
+itself will function fine. The next time garbage collection runs on A,
+the alternates connection gets established in Gitaly. This is done by
+`Projects::GitDeduplicationService` in gitlab-rails.
#### 2. SQL says repo A belongs to pool P1 but Gitaly says A has alternate objects in pool P2
-If we are not careful, this situation can lead to data loss. During some
-operations (repository maintenance), GitLab will try to re-link A to its
-pool P1. If this clobbers the existing link to P2, then A will loose Git
-objects and become invalid.
-
-Also, keep in mind that if GitLab's database got messed up, it may not
-even know that P2 exists.
-
-> TODO Ensure that Gitaly will not clobber existing, unexpected
-> alternates links. https://gitlab.com/gitlab-org/gitaly/issues/1534
+In this case `Projects::GitDeduplicationService` will throw an exception.
#### 3. SQL says repo A does not belong to any pool but Gitaly says A belongs to P
-This has the same data loss possibility as scenario 2 above.
+In this case `Projects::GitDeduplicationService` will try to
+"re-duplicate" the repository A using the DisconnectGitAlternates RPC.
## Git object deduplication and GitLab Geo
diff --git a/doc/development/gitaly.md b/doc/development/gitaly.md
index 4ef20d5fd74..c8beb808a54 100644
--- a/doc/development/gitaly.md
+++ b/doc/development/gitaly.md
@@ -245,7 +245,7 @@ Here are the steps to gate a new feature in Gitaly behind a feature flag.
// go implementation
} else {
findAllTagsRequests.WithLabelValues("ruby").Inc()
- // ruby impelmentation
+ // ruby implementation
}
```
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index 82439c94c5a..71e3b7740cb 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -17,7 +17,7 @@ our test design. We can find some helpful heuristics documented in the Handbook
## Run tests against MySQL
-By default, tests are only run againts PostgreSQL, but you can run them on
+By default, tests are only run against PostgreSQL, but you can run them on
demand against MySQL by following one of the following conventions:
| Convention | Valid example |
diff --git a/doc/development/testing_guide/end_to_end/quick_start_guide.md b/doc/development/testing_guide/end_to_end/quick_start_guide.md
index afe76acf9c9..9f43f4ebd1c 100644
--- a/doc/development/testing_guide/end_to_end/quick_start_guide.md
+++ b/doc/development/testing_guide/end_to_end/quick_start_guide.md
@@ -557,7 +557,7 @@ The code should look like this: `filter_output = search_field_tag search_id, nil
> Classes starting with `qa-` are used for testing purposes only, and by defining such classes in the elements we add **testability** in the application.
-> When defining a class like `qa-labels-block`, it is transformed into `:labels_block` for usage in the Page Objects. So, `qa-edit-link-labels` is tranformed into `:edit_link_labels`, `qa-dropdown-menu-labels` is transformed into `:dropdown_menu_labels`, and `qa-dropdown-input-field` is transformed into `:dropdown_input_field`. Also, we use a [sanity test](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/qa/page#how-did-we-solve-fragile-tests-problem) to check that defined elements have their respective `qa-` selectors in the specified views.
+> When defining a class like `qa-labels-block`, it is transformed into `:labels_block` for usage in the Page Objects. So, `qa-edit-link-labels` is transformed into `:edit_link_labels`, `qa-dropdown-menu-labels` is transformed into `:dropdown_menu_labels`, and `qa-dropdown-input-field` is transformed into `:dropdown_input_field`. Also, we use a [sanity test](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/qa/page#how-did-we-solve-fragile-tests-problem) to check that defined elements have their respective `qa-` selectors in the specified views.
> We did not define the `qa-labels-block` class in the `app/views/shared/issuable/_sidebar.html.haml` file because it was already there to be used.
diff --git a/doc/gitlab-basics/README.md b/doc/gitlab-basics/README.md
index 00ac6d6b650..0c268eff9f1 100644
--- a/doc/gitlab-basics/README.md
+++ b/doc/gitlab-basics/README.md
@@ -24,6 +24,7 @@ The following are guides to basic GitLab functionality:
- [Add an image](add-image.md), to add new images to a project's repository.
- [Create an issue](../user/project/issues/create_new_issue.md), to start collaborating within a project.
- [Create a merge request](add-merge-request.md), to request changes made in a branch be merged into a project's repository.
+- See how these features come together in the [GitLab Flow introduction video](https://youtu.be/InKNIvky2KE) and [GitLab Flow page](../workflow/gitlab_flow.md).
## Git basics
diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md
index 57a5a42fbed..6064c417900 100644
--- a/doc/integration/elasticsearch.md
+++ b/doc/integration/elasticsearch.md
@@ -351,8 +351,6 @@ There are several rake tasks available to you via the command line:
- This removes the GitLab index on the Elasticsearch instance.
- [sudo gitlab-rake gitlab:elastic:recreate_index](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/tasks/gitlab/elastic.rake)
- Does the same thing as `sudo gitlab-rake gitlab:elastic:create_empty_index`
-- [sudo gitlab-rake gitlab:elastic:add_feature_visibility_levels_to_project](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/tasks/gitlab/elastic.rake)
- - Adds visibility information to the indices for projects.
- [sudo gitlab-rake gitlab:elastic:index_snippets](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/tasks/gitlab/elastic.rake)
- Performs an Elasticsearch import that indexes the snippets data.
diff --git a/doc/migrate_ci_to_ce/README.md b/doc/migrate_ci_to_ce/README.md
index 4c4b423f40f..7659b743311 100644
--- a/doc/migrate_ci_to_ce/README.md
+++ b/doc/migrate_ci_to_ce/README.md
@@ -1,3 +1,7 @@
+---
+type: howto
+---
+
# Migrate GitLab CI to GitLab CE or EE
Beginning with version 8.0 of GitLab Community Edition (CE) and Enterprise
@@ -333,7 +337,9 @@ restoration](../raketasks/backup_restore.md) guide.
## Troubleshooting
### show:secrets problem (Omnibus-only)
+
If you see errors like this:
+
```
Missing `secret_key_base` or `db_key_base` for 'production' environment. The secrets will be generated and stored in `config/secrets.yml`
rake aborted!
@@ -344,6 +350,7 @@ This can happen if you are updating from versions prior to 7.13 straight to 8.0.
The fix for this is to update to Omnibus 7.14 first and then update it to 8.0.
### Permission denied when accessing /var/opt/gitlab/gitlab-ci/builds
+
To fix that issue you have to change builds/ folder permission before doing final backup:
```
sudo chown -R gitlab-ci:gitlab-ci /var/opt/gitlab/gitlab-ci/builds
@@ -355,8 +362,10 @@ sudo chown git:git /var/opt/gitlab/gitlab-ci/builds
```
### Problems when importing CI database to GitLab
+
If you were migrating CI database from MySQL to PostgreSQL manually you can see errors during import about missing sequences:
-```
+
+```sql
ALTER SEQUENCE
ERROR: relation "ci_builds_id_seq" does not exist
ERROR: relation "ci_commits_id_seq" does not exist
@@ -373,9 +382,9 @@ CREATE TABLE
To fix that you need to apply this SQL statement before doing final backup:
-```sql
-## Omnibus GitLab
+Omnibus GitLab installations:
+```sql
gitlab-ci-rails dbconsole <<EOF
-- ALTER TABLES - DROP DEFAULTS
ALTER TABLE ONLY ci_application_settings ALTER COLUMN id DROP DEFAULT;
@@ -428,9 +437,11 @@ ALTER TABLE ONLY ci_triggers ALTER COLUMN id SET DEFAULT nextval('ci_triggers_id
ALTER TABLE ONLY ci_variables ALTER COLUMN id SET DEFAULT nextval('ci_variables_id_seq'::regclass);
ALTER TABLE ONLY ci_web_hooks ALTER COLUMN id SET DEFAULT nextval('ci_web_hooks_id_seq'::regclass);
EOF
+```
-## Source installations
+Source installations:
+```
cd /home/gitlab_ci/gitlab-ci
sudo -u gitlab_ci -H bundle exec rails dbconsole production <<EOF
... COPY SQL STATEMENTS FROM ABOVE ...
diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md
index 1d656574acd..72bace3d282 100644
--- a/doc/policy/maintenance.md
+++ b/doc/policy/maintenance.md
@@ -1,8 +1,15 @@
-# GitLab Maintenance Policy
+---
+type: concepts
+---
+
+# GitLab Release and Maintenance Policy
+
+GitLab has strict policies governing version naming, as well as release pace for major, minor,
+patch and security releases. New releases are usually announced on the [GitLab blog](https://about.gitlab.com/blog/categories/releases/).
## Versioning
-GitLab follows the [Semantic Versioning](http://semver.org/) for its releases:
+GitLab uses [Semantic Versioning](http://semver.org/) for its releases:
`(Major).(Minor).(Patch)` in a [pragmatic way](https://gist.github.com/jashkenas/cbd2b088e20279ae2c8e).
For example, for GitLab version 10.5.7:
@@ -15,9 +22,9 @@ Any part of the version number can increment into multiple digits, for example,
The following table describes the version types and their release cadence:
-| Version type | Description | Cadence |
-|:-------------|:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Major | For significant changes, or when any backward-incompatible changes are introduced to the public API. | Yearly. The next major release is GitLab 12.0 on June 22, 2019. Subsequent major releases will be scheduled for May 22 each year, by default. | |
+| Version type | Description | Cadence |
+|:-------------|:------------|:--------|
+| Major | For significant changes, or when any backward-incompatible changes are introduced to the public API. | Yearly. The next major release is GitLab 12.0 on June 22, 2019. Subsequent major releases will be scheduled for May 22 each year, by default. |
| Minor | For when new backward-compatible functionality is introduced to the public API, a minor feature is introduced, or when a set of smaller features is rolled out. | Monthly on the 22nd. |
| Patch | For backward-compatible bug fixes that fix incorrect behavior. See [Patch releases](#patch-releases). | As needed. |
@@ -75,10 +82,10 @@ that could change behavior in the next major release.
Please see the table below for some examples:
| Latest stable version | Your version | Recommended upgrade path | Note |
-| -------------- | ------------ | ------------------------ | ---------------- |
-| 9.4.5 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.4.5` | `8.17.7` is the last version in version `8` |
-| 10.1.4 | 8.13.4 | `8.13.4 -> 8.17.7 -> 9.5.10 -> 10.1.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9` |
-| 11.3.4 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9`, `10.8.7` is the last version in version `10` |
+| --------------------- | ------------ | ------------------------ | ---- |
+| 9.4.5 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.4.5` | `8.17.7` is the last version in version `8` |
+| 10.1.4 | 8.13.4 | `8.13.4 -> 8.17.7 -> 9.5.10 -> 10.1.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9` |
+| 11.3.4 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9`, `10.8.7` is the last version in version `10` |
More information about the release procedures can be found in our
[release documentation](https://gitlab.com/gitlab-org/release/docs). You may also want to read our
diff --git a/doc/public_access/public_access.md b/doc/public_access/public_access.md
index 8601551e3bd..b1637181855 100644
--- a/doc/public_access/public_access.md
+++ b/doc/public_access/public_access.md
@@ -1,13 +1,12 @@
-# Public access
-
-GitLab allows [Owners](../user/permissions.md) to change a projects' visibility in order to be accessed
-**publicly** or **internally**.
+---
+type: reference
+---
-Projects with either of these visibility levels will be listed in the
-public access directory (`/public` under your GitLab instance).
-Here is the [GitLab.com example](https://gitlab.com/public).
+# Public access
-Internal projects will only be available to authenticated users.
+GitLab allows [Owners](../user/permissions.md) to set a projects' visibility as **public**, **internal**
+or **private**. These visibility levels affect who can see the project in the
+public access directory (`/public` under your GitLab instance), like at [https://gitlab.com/public]().
## Visibility of projects
@@ -15,26 +14,26 @@ Internal projects will only be available to authenticated users.
Public projects can be cloned **without any** authentication.
-They will also be listed on the public access directory (`/public`).
+They will be listed in the public access directory (`/public`) for all users.
-**Any logged in user** will have [Guest](../user/permissions.md)
-permissions on the repository.
+**Any logged in user** will have [Guest permissions](../user/permissions.md)
+on the repository.
### Internal projects
Internal projects can be cloned by any logged in user.
-They will also be listed on the public access directory (`/public`) for logged
+They will also be listed in the public access directory (`/public`), but only for logged
in users.
-Any logged in user will have [Guest](../user/permissions.md) permissions
+Any logged in user will have [Guest permissions](../user/permissions.md)
on the repository.
### Private projects
-Private projects can only be cloned and viewed by project members, and
-they will only appear to project members on the public access directory
-(`https://gitlab.example.com/public`).
+Private projects can only be cloned and viewed by project members.
+
+They will appear in the public access directory (`/public`) for project members only.
### How to change project visibility
@@ -43,10 +42,10 @@ they will only appear to project members on the public access directory
## Visibility of groups
->**Note:**
-[Starting with][3323] GitLab 8.6, the group visibility has changed and can be
-configured the same way as projects. In previous versions, a group's page was
-always visible to all users.
+NOTE: **Note:**
+[Starting with](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3323) GitLab 8.6,
+the group visibility has changed and can be configured the same way as projects.
+In previous versions, a group's page was always visible to all users.
Like with projects, the visibility of a group can be set to dictate whether
anonymous users, all signed in users, or only explicit group members can view
@@ -54,8 +53,6 @@ it. The restriction for visibility levels on the application setting level also
applies to groups, so if that's set to internal, the explore page will be empty
for anonymous users. The group page now has a visibility level icon.
-[3323]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3323
-
## Visibility of users
The public page of a user, located at `/username`, is always visible whether
@@ -76,3 +73,15 @@ snippet:
This is useful to prevent people exposing their repositories to public
by accident. The restricted visibility settings do not apply to admin users.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/push_rules/push_rules.md b/doc/push_rules/push_rules.md
index e44eab2556e..b2d626a0a74 100644
--- a/doc/push_rules/push_rules.md
+++ b/doc/push_rules/push_rules.md
@@ -1,6 +1,11 @@
+---
+type: reference, howto
+---
+
# Push Rules **[STARTER]**
-Gain additional control over pushes to your repository.
+Gain additional control over what can and can't be pushed to your repository by using
+regular expressions to reject pushes based on commit contents, branch names or file details.
## Overview
@@ -33,7 +38,7 @@ will be accepted.
### Restrict branch names
-Let's assume there's a strictly policy for branch names in your company, and
+Let's assume there's a strict policy for branch names in your company, and
you want the branches to start with a certain name because you have different
GitLab CI jobs (`feature`, `hotfix`, `docker`, `android`, etc.) that rely on the
branch name.
@@ -46,7 +51,7 @@ will get rejected.
## Enabling push rules
->**Note:**
+NOTE: **Note:**
GitLab administrators can set push rules globally under
**Admin area > Push Rules** that all new projects will inherit. You can later
override them in a project's settings.
@@ -71,8 +76,8 @@ The following options are available.
| Prohibited file names | **Starter** 7.10 | Any committed filenames that match this regular expression are not allowed to be pushed. Leave empty to allow any filenames. |
| Maximum file size | **Starter** 7.12 | Pushes that contain added or updated files that exceed this file size (in MB) are rejected. Set to 0 to allow files of any size. |
->**Tip:**
-GitLab uses [RE2 syntax](https://github.com/google/re2/wiki/Syntax) for regular expressions in push rules. You can check your regular expressions at <https://regex-golang.appspot.com>.
+TIP: **Tip:**
+GitLab uses [RE2 syntax](https://github.com/google/re2/wiki/Syntax) for regular expressions in push rules, and you can test them at the [GoLang regex tester](https://regex-golang.appspot.com).
## Prevent pushing secrets to the repository
@@ -86,7 +91,7 @@ pushes to the repository when a file matches a regular expression as read from
[`files_blacklist.yml`][list] (make sure you are at the right branch
as your GitLab version when viewing this file).
-NOTE: **Note**:
+NOTE: **Note:**
Files already committed won't get restricted by this push rule.
Below is an example list of what will be rejected by these regular expressions:
@@ -148,6 +153,18 @@ pry.history
bash_history
```
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
+
[protected-branches]: ../user/project/protected_branches.md
[signing-commits]: ../user/project/repository/gpg_signed_commits/index.md
[ee-385]: https://gitlab.com/gitlab-org/gitlab-ee/issues/385
diff --git a/doc/ssh/README.md b/doc/ssh/README.md
index 3bfebfc5d9b..09b5fbd9260 100644
--- a/doc/ssh/README.md
+++ b/doc/ssh/README.md
@@ -1,3 +1,7 @@
+---
+type: howto, reference
+---
+
# GitLab and SSH keys
Git is a distributed version control system, which means you can work locally
@@ -50,8 +54,7 @@ more information, you can read this
We'll focus on ED25519 and RSA and here.
NOTE: **Note:**
-As an admin, you can restrict
-[which keys should be permitted and their minimum length](../security/ssh_keys_restrictions.md).
+As an admin, you can [restrict which keys should be permitted and their minimum length](../security/ssh_keys_restrictions.md).
By default, all keys are permitted, which is also the case for
[GitLab.com](../user/gitlab_com/index.md#ssh-host-keys-fingerprints).
@@ -91,9 +94,8 @@ ssh-keygen -o -f ~/.ssh/id_rsa
## Generating a new SSH key pair
-Before creating an SSH key pair, make sure to read about the
-[different types of keys](#types-of-ssh-keys-and-which-to-choose) to understand
-their differences.
+Before creating an SSH key pair, make sure to understand the
+[different types of keys](#types-of-ssh-keys-and-which-to-choose).
To create a new SSH key pair:
@@ -332,7 +334,7 @@ not implicitly give any access just by setting them up.
### Eclipse
-How to add your SSH key to Eclipse: <https://wiki.eclipse.org/EGit/User_Guide#Eclipse_SSH_Configuration>
+If you are using [EGit](https://www.eclipse.org/egit/), you can [add your SSH key to Eclipse](https://wiki.eclipse.org/EGit/User_Guide#Eclipse_SSH_Configuration).
## SSH on the GitLab server
diff --git a/doc/subscriptions/index.md b/doc/subscriptions/index.md
index 9b0aa5aa272..37051f6b10f 100644
--- a/doc/subscriptions/index.md
+++ b/doc/subscriptions/index.md
@@ -1,3 +1,7 @@
+---
+type: index, reference
+---
+
# Subscription setup and management
This page will help get you started with your new subscription or manage an existing one, whether you have subscribed to GitLab.com or self-managed GitLab.
@@ -42,7 +46,8 @@ After purchase, the license file is sent to the email address tied to the Custom
### Link your GitLab.com account with your Customers Portal account
-NOTE: **Note:** This is *required* for GitLab.com subscriptions.
+NOTE: **Note:**
+This is *required* for GitLab.com subscriptions.
Once signed into the customers portal, if your account is not already linked, you should be prompted to link your account with a "Link my GitLab Account" button.
@@ -109,3 +114,15 @@ These issues are the best avenue for getting updates on specific product plans a
### Contacting Support
Learn more about the tiers of [GitLab Support](https://about.gitlab.com/support/) or [submit a request via the Support Portal](https://support.gitlab.com/hc/en-us/requests/new).
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md
index a3698d60f6d..a46f7d30892 100644
--- a/doc/system_hooks/system_hooks.md
+++ b/doc/system_hooks/system_hooks.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# System hooks
Your GitLab instance can perform HTTP POST requests on the following events:
@@ -27,11 +31,9 @@ The triggers for most of these are self-explanatory, but `project_update` and `p
System hooks can be used, e.g. for logging or changing information in a LDAP server.
-> **Note:**
->
-> We follow the same structure from Webhooks for Push and Tag events, but we never display commits.
->
-> Same deprecations from Webhooks are valid here.
+NOTE: **Note:**
+We follow the same structure and deprecations as [Webhooks](../user/project/integrations/webhooks.md)
+for Push and Tag events, but we never display commits.
## Hooks request example
@@ -640,3 +642,15 @@ X-Gitlab-Event: System Hook
"refs":["refs/heads/master"]
}
```
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/tools/email.md b/doc/tools/email.md
index ab39206ffa4..a2d677484f0 100644
--- a/doc/tools/email.md
+++ b/doc/tools/email.md
@@ -1,12 +1,12 @@
-# Email from GitLab **[STARTER ONLY]**
-
-As a GitLab administrator you can email GitLab users from within GitLab.
+---
+type: howto, reference
+---
-## Overview
+# Email from GitLab **[STARTER ONLY]**
-GitLab provides a simple tool to email all users or users of a chosen group or
-project right from the admin area. Users will receive the email to their primary
-email address.
+GitLab provides a simple tool to administrators for emailing all users, or users of
+a chosen group or project, right from the admin area. Users will receive the email
+at their primary email address.
## Use-cases
@@ -28,11 +28,21 @@ email address.
## Unsubscribing from emails
-User can choose to unsubscribe from receiving emails from GitLab by following
-the unsubscribe link from the email. Unsubscribing is unauthenticated in order
-to keep the simplicity of this feature.
+Users can choose to unsubscribe from receiving emails from GitLab by following
+the unsubscribe link in the email. Unsubscribing is unauthenticated in order
+to keep this feature simple.
-On unsubscribe, user will receive an email notifying that unsubscribe happened.
+On unsubscribe, users will receive an email notification that unsubscribe happened.
The endpoint that provides the unsubscribe option is rate-limited.
-[ee]: https://about.gitlab.com/pricing/
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index 8c132570577..34140a3260e 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -14,6 +14,8 @@ with minimal configuration. Just push your code and GitLab takes
care of everything else. This makes it easier to start new projects and brings
consistency to how applications are set up throughout a company.
+For an introduction to Auto DevOps, watch [AutoDevOps in GitLab 11.0](https://youtu.be/0Tc0YYBxqi4).
+
## Enabled by default
Starting with GitLab 11.3, the Auto DevOps pipeline is enabled by default for all
diff --git a/doc/university/README.md b/doc/university/README.md
index 880b91387c0..c116e54ad48 100644
--- a/doc/university/README.md
+++ b/doc/university/README.md
@@ -78,7 +78,6 @@ The GitLab University curriculum is composed of GitLab videos, screencasts, pres
### 1.8 GitLab Training Material
-1. [Git and GitLab Terminology](glossary/README.md)
1. [Git and GitLab Workshop - Slides](https://docs.google.com/presentation/d/1JzTYD8ij9slejV2-TO-NzjCvlvj6mVn9BORePXNJoMI/edit?usp=drive_web)
## 2. GitLab Intermediate
diff --git a/doc/university/glossary/README.md b/doc/university/glossary/README.md
index f15b0107de5..21e2da3e47c 100644
--- a/doc/university/glossary/README.md
+++ b/doc/university/glossary/README.md
@@ -2,707 +2,10 @@
comments: false
---
-# What is the Glossary
+# Glossary
-This contains a simplified list and definitions of some of the terms that you will encounter in your day to day activities when working with GitLab.
-Please add any terms that you discover that you think would be useful for others.
+This page has been removed after an effort to ensure that all applicable GitLab-specific
+terms are available in context on the relevant [GitLab Documentation](https://docs.gitlab.com/)
+or [about.gitlab.com](https://about.gitlab.com/) pages.
-### 2FA
-
-User authentication by combination of 2 different steps during login. This allows for [more security](https://about.gitlab.com/handbook/security/).
-
-### Access Levels
-
-Process of selective restriction to create, view, modify or delete a resource based on a set of assigned permissions. See [GitLab's Permission Guidelines](../../user/permissions.md)
-
-### Active Directory (AD)
-
-A Microsoft-based [directory service](https://msdn.microsoft.com/en-us/library/bb742424.aspx) for windows domain networks. It uses LDAP technology under the hood.
-
-### Agile
-
-Building and [delivering software](http://agilemethodology.org/) in phases/parts rather than trying to build everything at once then delivering to the user/client. The latter is known as the WaterFall model.
-
-### Amazon RDS
-
-External reference: <http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html>
-
-### Application Lifecycle Management (ALM)
-
-The entire product lifecycle management process for an application, from requirements management, development, and testing until deployment. GitLab has [advantages](https://docs.google.com/presentation/d/1vCU-NbZWz8NTNK8Vu3y4zGMAHb5DpC8PE5mHtw1PWfI/edit#slide=id.g72f2e4906_2_288) over both legacy and modern ALM tools.
-
-### Artifactory
-
-A version control [system](https://www.jfrog.com/open-source/#os-arti) for non-text files.
-
-### Artifacts
-
-Objects (usually binary and large) created by a build process. These can include use cases, class diagrams, requirements and design documents.
-
-### Atlassian
-
-A [company](https://www.atlassian.com) that develops software products for developers and project managers including Bitbucket, Jira, Hipchat, Confluence, Bamboo.
-
-### Audit Log
-
-Also called an [audit trail](https://en.wikipedia.org/wiki/Audit_trail), an audit log is a document that records an event in an IT system.
-
-### Auto Defined User Group
-
-User groups are a way of centralizing control over important management tasks, particularly access control and password policies. A simple example of such groups are the users and the admins groups.
-In most of the cases these groups are auto defined in terms of access, rules of usage, conditions to be part of, etc.
-
-### Bamboo
-
-Atlassian's CI tool similar to GitLab CI and Jenkins.
-
-### Basic Subscription
-
-Entry level [subscription](https://about.gitlab.com/pricing/) for GitLab EE currently available in packs of 10.
-
-### Bitbucket
-
-Atlassian's web hosting service for Git and Mercurial Projects. Read about [migrating](../../user/project/import/bitbucket.md) from BitBucket to a GitLab instance.
-
-### Branch
-
-A branch is a parallel version of a repository. This allows you to work on the repository without affecting the "master" branch, and without affecting the current "live" version. When you have made all your changes to your branch you can then merge to the master. When your merge request is accepted your changes will be "live."
-
-### Branded Login
-
-Having your own logo on [your GitLab instance login page](../../customization/branded_login_page.md) instead of the GitLab logo.
-
-### Job triggers (Build Triggers)
-These protect your code base against breaks, for instance when a team is working on the same project. Learn about [setting up](../../ci/triggers/README.md) job triggers.
-
-### CEPH
-
- A distributed object store and file [system](http://ceph.com/) designed to provide excellent performance, reliability and scalability.
-
-### ChatOps
-
-The ability to [initiate an action](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/1412) from chat. ChatBots run in your chat application and give you the ability to do "anything" from chat.
-
-### Clone
-
-A [copy](https://git-scm.com/docs/git-clone) of a repository stored on your machine that allows you to use your own editor without being online, but still tracks the changes made remotely.
-
-### Code Review
-
-Examination of a program's code. The main aim is to maintain high quality standards of code that is being shipped. Merge requests [serve as a code review tool](https://about.gitlab.com/2014/09/29/gitlab-flow/) in GitLab.
-
-### Code Snippet
-
-A small amount of code, usually selected for the purpose of showing other developers how to do something specific or reproduce a problem.
-
-### Collaborator
-
-Person with read and write access to a repository who has been invited by repository owner.
-
-### Commit
-
-A [change](https://git-scm.com/docs/git-commit) (revision) to a file that also creates an ID, allowing you to see revision history and the author of the changes.
-
-### Community
-
-[Everyone](https://about.gitlab.com/community/) who uses GitLab.
-
-### Confluence
-
-Atlassian's product for collaboration on documents and projects.
-
-### Continuous Delivery
-
-A [software engineering approach](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) in which continuous integration, automated testing, and automated deployment capabilities allow software to be developed and deployed rapidly, reliably and repeatedly with minimal human intervention. Still, the deployment to production is defined strategically and triggered manually. [Amazon moves toward continuous delivery](https://www.youtube.com/watch?v=esEFaY0FDKc)
-
-### Continuous Deployment
-
-A [software development practice](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) in which every code change goes through the entire pipeline and is put into production automatically, resulting in many production deployments every day. It does everything that Continuous Delivery does, but the process is fully automated, there's no human intervention at all. [The difference between Continuous Delivery and Continuous Integration.](https://www.youtube.com/watch?v=igwFj8PPSnw)
-
-### Continuous Integration
-
-A [software development practice](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) in which you build and test software every time a developer pushes code to the application, and it happens several times a day. [Thoughtworks discusses continuous integration.](https://www.thoughtworks.com/continuous-integration)
-
-### Contributor
-
-Term used for a person contributing to an open source project.
-
-### Conversational Development (ConvDev)
-
-A [natural evolution](https://about.gitlab.com/2016/09/14/gitlab-live-event-recap/) of software development that carries a conversation across functional groups throughout the development process, enabling developers to track the full path of development in a cohesive and intuitive way. ConvDev accelerates the development lifecycle by fostering collaboration and knowledge sharing from idea to production.
-
-### Cycle Analytics
-
-See <https://gitlab.com/gitlab-org/gitlab-ce/issues/22458>
-
-### Cycle Time
-
-The time it takes to move from [idea to production](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#from-idea-to-production-with-gitlab).
-
-### Data Centre
-
-Atlassian product for High Availability.
-
-### Dependencies
-
-As in "specify [dependencies](https://gitlab.com/gitlab-org/gitlab-ce/issues/14728) between stages."
-
-### Deploy Keys
-
-A [SSH key](../../gitlab-basics/create-your-ssh-keys.md)stored on your server that grants access to a single GitLab repository. This is used by a GitLab runner to clone a project's code so that tests can be run against the checked out code.
-
-### Developer
-
-For us at GitLab, this means a software developer, or someone who makes software. It is also one of the levels of access in our multi-level approval system.
-
-### DevOps
-
-The intersection of software engineering, quality assurance, and technology operations. Explore more DevOps topics in the [glossary by XebiaLabs](https://xebialabs.com/glossary/)
-
-### Diff
-
-The difference between two commits, or saved changes. This will also be shown visually after the changes.
-
-### Directory
-
-A folder used for storing multiple files.
-
-### Docker Container Registry
-
-A [feature](../../user/project/container_registry.md) of [GitLab projects](https://about.gitlab.com/2016/05/23/gitlab-container-registry/). Containers wrap up a piece of software in a complete filesystem that contains everything it needs to run: code, runtime, system tools, system libraries – anything you can install on a server. This guarantees that it will always run the same, regardless of the environment it is running in.
-
-### Dynamic Environment (review apps)
-
-### EC2 Instance
-
-### Elasticsearch
-
-Elasticsearch is a flexible, scalable and powerful search service. When [enabled](https://gitlab.com/help/integration/elasticsearch.md), it helps keep GitLab's search fast when dealing with a huge amount of data.
-
-### Emacs
-
-External reference: <https://www.masteringemacs.org/article/mastering-key-bindings-emacs>
-
-### First Byte
-
-External reference: <https://en.wikipedia.org/wiki/Time_To_First_Byte>
-
-First Byte (sometimes referred to as time to first byte or [TTFB](https://en.wikipedia.org/wiki/Time_To_First_Byte)) measures the time between making a request and receiving the first byte of information in return. As a result, First Byte encompasses everything that is the backend as well as network transit issues. It differs from [_Speed Index_](#speed-index) mostly by frontend related issues which are included in Speed Index such as javascript loading, page rendering, and so on.
-
-### Fork
-
-Your [own copy](../../workflow/forking_workflow.md) of a repository that allows you to make changes to the repository without affecting the original.
-
-### Funnel, or: TOFU, MOFU, BOFU
-
-External reference: [Blog post](https://www.weidert.com/whole_brain_marketing_blog/bid/113688/ToFu-MoFu-BoFu-Serving-Up-The-Right-Content-for-Lead-Nurturing)
-
-TOFU: top of funnel
-MOFU: middle of funnel
-BOFU: bottom of funnel
-
-### Gerrit
-
-A code review [tool](https://www.gerritcodereview.com/) built on top of Git.
-
-### Git Attributes
-
-A [git attributes file](https://git-scm.com/docs/gitattributes) is a simple text file that gives attributes to pathnames.
-
-### Git Hooks
-
-[Scripts](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) you can use to trigger actions at certain points.
-
-Difference between a [webhook](#webhooks) and a git hook: a git hook is local to its repo (usually) while a webhook is not (it can make API or http calls). So for example if you want your linter to fire before you commit, you can set that up with a git hook. If the linter fails, the commit does not go through. A git hook _can_ be configured to go beyond its repo, e.g. by having it make an API call.
-
-### GitHost.io
-
-A single-tenant solution that provides GitLab CE or EE as a managed service. GitLab Inc. is responsible for installing, updating, hosting, and backing up customers' own private and secure GitLab instance.
-
-### GitHub
-
-A web-based Git repository hosting service with an enterprise offering. Its main features are: issue tracking, pull request with code review, abundancy of integrations and wiki. It offers free public repos, private repos and enterprise services are paid. Read about [importing a project](../../workflow/importing/import_projects_from_github.md) from GitHub to GitLab.
-
-### GitLab CE
-
-Our free on Premise solution with >100,000 users
-
-### GitLab CI
-
-Our own Continuous Integration [feature](https://about.gitlab.com/gitlab-ci/) that is shipped with each instance
-
-### GitLab EE
-
-Our premium on premise [solution](https://about.gitlab.com/features/#enterprise) that currently has Basic, Standard and Plus subscription packages with additional features and support.
-
-### GitLab.com
-
-Our free SaaS for public and private repositories.
-
-### GitLab Geo
-
-Allows you to replicate your GitLab instance to other geographical locations as a read-only fully operational version. It [can be used](../../administration/geo/replication/index.md) for cloning and fetching projects, in addition to reading any data. This will make working with large repositories over large distances much faster.
-
-### GitLab High Availability
-
-### GitLab Master Plan
-
-Related blog post: <https://about.gitlab.com/2016/09/13/gitlab-master-plan/>.
-
-### GitLab Pages
-
-These allow you to [create websites](https://gitlab.com/help/pages/README.md) for your GitLab projects, groups, or user account.
-
-### GitLab Runner
-
-Related project: <https://gitlab.com/gitlab-org/gitlab-runner>
-
-### Gitolite
-
-An [access layer](https://git-scm.com/book/en/v1/Git-on-the-Server-Gitolite) that sits on top of Git. Users are granted access to repos via a simple config file. As an admin, you only need the users' public SSH key and a username.
-
-### Gitorious
-
-A web-based hosting service for projects using Git. It was acquired by GitLab and we discontinued the service. Read the[Gitorious Acquisition Blog Post](https://about.gitlab.com/2015/03/03/gitlab-acquires-gitorious/).
-
-### Go
-
-An open source programming [language](https://golang.org/).
-
-### Gogs
-
-External reference: <https://gogs.io/>
-
-### GUI/ Git GUI
-
-A portable [graphical interface](https://git-scm.com/docs/git-gui) to Git that allows users to make changes to their repository by making new commits, amending existing ones, creating branches, performing local merges, and fetching/pushing to remote repositories.
-
-### High Availability for Disaster Recovery (HADR)
-
-Sometimes written HA/DR, this usually refers to a strategy for having a failover server in place in case the main server fails.
-
-### Hip Chat
-
-Atlassian's real time chat application for teams, Hip Chat is a competitor to Slack, RocketChat and MatterMost.
-
-### High Availability
-
-Refers to a [system or component](https://about.gitlab.com/high-availability/) that is continuously operational for a desirably long length of time. Availability can be measured relative to "100% operational" or "never failing."
-
-### Inner-sourcing
-
-The [use of](https://about.gitlab.com/2014/09/05/innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization/) open source development techniques within the corporation.
-
-### Internet Relay Chat (IRC)
-
-An [application layer protocol](http://www.irchelp.org/) that facilitates communication in the form of text.
-
-### Issue Tracker
-
-A [tool](../../integration/external-issue-tracker.md) used to manage, organize, and maintain a list of issues, making it easier for an organization to manage.
-
-### Jenkins
-
-An Open Source CI tool written using the Java programming language. [Jenkins](https://jenkins.io/) does the same job as GitLab CI, Bamboo, and Travis CI. It is extremely popular. Related [documentation](../../integration/jenkins.md).
-
-### Jira
-
-Atlassian's [project management software](https://www.atlassian.com/software/jira), i.e. a complex issue tracker. GitLab [can be configured](../../project_services/jira.md) to interact with JIRA Core either using an on-premise instance or the SaaS solution that Atlassian offers.
-
-### JUnit
-
-A testing framework for the Java programming language, [JUnit](http://junit.org/junit4/) has been important in the evolution of test-driven development.
-
-### Kerberos
-
-A network authentication [protocol](http://web.mit.edu/kerberos/) that uses secret-key cryptography for security.
-
-### Kubernetes
-
-An open source container cluster manager originally designed by Google. It's basically a platform for automating deployment, scaling, and operations of application containers over clusters of hosts.
-
-### Labels
-
-An [identifier](../../user/project/labels.md) to describe a group of one or more specific file revisions.
-
-### Lightweight Directory Access Protocol (LDAP)
-
- A directory (electronic address book) with user information (e.g. name, phone_number etc.)
-
-### LDAP User Authentication
-
-GitLab [integrates](../../administration/auth/ldap.md) with LDAP to support user authentication. This enables GitLab to sign in people from an LDAP server (i.e., allowing people whose names are on the electronic user directory server to be able to use their LDAP accounts to login.)
-
-### LDAP Group Sync
-
-Allows you to synchronize the members of a GitLab group with one or more LDAP groups.
-
-### Lint
-
-Static code analysis for our various file types. For example, we use [scss-lint](https://github.com/brigade/scss-lint) to ensure that a consistent code styling is respected. Similar tools: rubocop / eslint.
-
-### Load Balancer
-
-A [device](https://en.wikipedia.org/wiki/Load_balancing_(computing)) that distributes network or application traffic across multiple servers.
-
-### Git Large File Storage (LFS)
-
-A way [to enable](https://about.gitlab.com/2015/11/23/announcing-git-lfs-support-in-gitlab/) git to handle large binary files by using reference pointers within small text files to point to the large files. Large files such as high resolution images and videos, audio files, and assets can be called from a remote server.
-
-### Linux
-
-An operating system like Windows or OS X. It is mostly used by software developers and on servers.
-
-### Markdown
-
-A lightweight markup language with plain text formatting syntax designed so that it can be converted to HTML and many other formats using a tool by the same name. Markdown is often used to format readme files, for writing messages in online discussion forums, and to create rich text using a plain text editor. Checkout GitLab's [Markdown guide](https://gitlab.com/help/user/markdown.md).
-
-### Maria DB
-
-A community developed fork/variation of MySQL. MySQL is owned by Oracle.
-
-### Master
-
-Name of the [default branch](https://git-scm.com/book/en/v1/Git-Branching-What-a-Branch-Is) in every git repository.
-
-### Mattermost
-
-An open source, self-hosted messaging alternative to Slack. View GitLab's Mattermost [feature](https://gitlab.com/gitlab-org/gitlab-mattermost).
-
-### Mercurial
-
-A free distributed version control system similar to and a competitor with Git.
-
-### Merge
-
-Takes changes from one branch, and [applies them](https://git-scm.com/docs/git-merge) into another branch.
-
-### Merge Conflict
-
-[Arises](https://about.gitlab.com/2016/09/06/resolving-merge-conflicts-from-the-gitlab-ui/) when a merge can't be performed cleanly between two versions of the same file.
-
-#### Merge Request (MR)
-
-[Takes changes](../../gitlab-basics/add-merge-request.md) from one branch, and applies them into another branch.
-
-### Meteor
-
-A [platform](https://www.meteor.com) for building javascript apps.
-
-### Milestones
-
-Allow you to [organize issues](../../user/project/milestones/index.md) and merge requests in GitLab into a cohesive group, optionally setting a due date. A common use is keeping track of an upcoming software version. Milestones are created per-project.
-
-### Mirror Repositories
-
-A project that is set up to automatically have its branches, tags, and commits [updated from an upstream repository](../../workflow/repository_mirroring.md). This is useful when a repository you're interested in is located on a different server, and you want to be able to browse its content and activity using the familiar GitLab interface.
-
-### MIT License
-
-A type of software license. It lets people do anything with your code with proper attribution and without warranty. It is the most common license for open source applications written in Ruby on Rails. GitLab CE is issued under this [license](../../development/licensing.md). This means you can download the code, modify it as you want, and even build a new commercial product using the underlying code and it's not illegal. The only condition is that there is no form of warranty provided by GitLab so whatever happens when you use the code is your own problem.
-
-### Mondo Rescue
-
-A free disaster recovery [software](https://help.ubuntu.com/community/MondoMindi).
-
-#### Mount
-
-External reference:
-
-As stated on the [wikipedia page](https://en.wikipedia.org/wiki/Mount_(Unix)), "Mounting makes file systems, files, directories, devices and special files available for use and available to the user."
-
-For example, we have NFS servers where the _git files_ reside. In order for a worker node to "see" or "use" the git files, the NFS server needs to be _mounted_ on the worker; that is, the worker needs to know that the NFS server exists and how to connect to it. Think of it as getting a shared drive to show up in your Finder (on Mac) or Explorer (on Windows).
-
-### MySQL
-
-A relational [database](http://www.mysql.com/) owned by Oracle. Currently only supported if you are using EE.
-
-### Namespace
-
-A set of symbols that are used to organize objects of various kinds so that these objects may be referred to by name. Examples of namespaces in action include file systems that assign names to files; programming languages that organize their variables and subroutines in namespaces; and computer networks and distributed systems that assign names to resources, such as computers, printers, websites, (remote) files, etc.
-
-### Nginx
-
-A web [server](https://www.nginx.com/resources/wiki/) (pronounced "engine x"). [It can act](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/nginx.md) as a reverse proxy server for HTTP, HTTPS, SMTP, POP3, and IMAP protocols, as well as a load balancer and an HTTP cache.
-
-### OAuth
-
-An open standard for authorization, commonly used as a way for internet users to log into third party websites using their Microsoft, Google, Facebook or Twitter accounts without exposing their password. GitLab [is](../../integration/oauth_provider.md) an OAuth2 authentication service provider.
-
-### Omnibus Packages
-
-A way to [package different services and tools](https://docs.gitlab.com/omnibus/) required to run GitLab, so that most developers can install it without laborious configuration.
-
-### On Premise
-
-On your own server. In GitLab, this [refers](https://about.gitlab.com/2015/02/12/why-ship-on-premises-in-the-saas-era/) to the ability to download GitLab EE/GitLab CE and host it on your own server rather than using GitLab.com, which is hosted by GitLab Inc's servers.
-
-### Open Core
-
-GitLab's [business model](https://about.gitlab.com/2016/07/20/gitlab-is-open-core-github-is-closed-source/). Coined by Andrew Lampitt in 2008, the [open core model](https://en.wikipedia.org/wiki/Open_core) primarily involves offering a "core" or feature-limited version of a software product as free and open-source software, while offering "commercial" versions or add-ons as proprietary software.
-
-### Open Source Software
-
-Software for which the original source code is freely [available](https://opensource.org/docs/osd) and may be redistributed and modified. GitLab prioritizes open source [stewardship](https://about.gitlab.com/2016/01/11/being-a-good-open-source-steward/). Including to providing access to the source code, open source software must comply with a number of criteria, among them free distribution and no discrimination against persons, groups, or fields of endeavor.
-
-#### Open Source Stewardship
-
-[Related blog post](https://about.gitlab.com/2016/01/11/being-a-good-open-source-steward/).
-
-### Owner
-
-The most powerful person on a GitLab project. They have the permissions of all the other users plus the additional permission of being able to destroy (i.e. delete) the project.
-
-### Platform as a Service (PaaS)
-
-Typically referred to in regards to application development, PaaS is a model in which a cloud provider delivers hardware and software tools to its users as a service.
-
-### Perforce
-
-The company that produces Helix. A commercial, proprietary, centralised VCS well known for its ability to version files of any size and type. They OEM a re-branded version of GitLab called "GitSwarm" that is tightly integrated with their "GitFusion" product, which in turn represents a portion of a Helix repository (called a depot) as a git repo.
-
-### Phabricator
-
-A suite of web-based software development collaboration tools, including the Differential code review tool, the Diffusion repository browser, the Herald change monitoring tool, the Maniphest bug tracker and the Phriction wiki. Phabricator integrates with Git, Mercurial, and Subversion.
-
-### Piwik Analytics
-
-An open source analytics software to help you analyze web traffic. It is similar to Google Analytics, except that the latter is not open source and information is stored by Google. In Piwik, the information is stored on your own server and hence is fully private.
-
-### Plus Subscription
-
-GitLab Premium EE [subscription](https://about.gitlab.com/pricing/) that includes training and dedicated Account Management and Service Engineer and complete support package.
-
-### PostgreSQL
-
-An [object-relational](https://en.wikipedia.org/wiki/PostgreSQL) database. Touted as the most advanced open source database, it is one of two database management systems [supported by](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/database.md) GitLab, the other being MySQL.
-
-### Protected Branches
-
-A [feature](../../user/project/protected_branches.md) that protects branches from unauthorized pushes, force pushing or deletion.
-
-### Protected Tags
-
-A [feature](../../user/project/protected_tags.md) that protects tags from unauthorized creation, update or deletion
-
-### Pull
-
-Git command to [synchronize](https://git-scm.com/docs/git-pull) the local repository with the remote repository, by fetching all remote changes and merging them into the local repository.
-
-### Puppet
-
-A popular DevOps [automation tool](https://puppet.com/product/how-puppet-works).
-
-### Push
-
-Git [command](https://git-scm.com/docs/git-push) to send commits from the local repository to the remote repository. Read about [advanced push rules](https://gitlab.com/help/pages/README.md) in GitLab.
-
-### Raketasks
-
-### RE Read Only
-
-Permissions to see a file and its contents, but not change it.
-
-### Rebase
-
-In addition to the merge, the [rebase](https://git-scm.com/book/en/v2/Git-Branching-Rebasing) is a main way to integrate changes from one branch into another.
-
-### Regression
-
-A regression is something that used to work one way in the last release and then we made a **breaking change** and it no longer works the same way.
-
-_or_
-
-A regression is defined as a change that results in a negative impact on the functionality of an existing feature due to recent changes, i.e. the latest release.
-
-### Remote mirroring
-
-### (Git) Repository
-
-A directory where Git [has been initiatlized](https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository) to start version controlling your files. The history of your work is stored here. A remote repository is not on your machine, but usually online (like on GitLab.com, for instance). The main remote repository is usually called "Origin."
-
-##### Remote repository
-
-A [repository](https://about.gitlab.com/2015/05/18/simple-words-for-a-gitlab-newbie/) that is not-on-your-machine, so it's anything that is not your computer. Usually, it is online, GitLab.com for instance. The main remote repository is usually called “Origin”.
-
-### Requirements management
-
-Gives your distributed teams a single shared repository to collaborate and share requirements, understand their relationship to tests, and evaluate linked defects. It includes multiple, preconfigured requirement types.
-
-### Revision Control
-
-Also known as version control or source control, this is the management of changes to documents, computer programs, large web sites, and other collections of information. Changes are usually identified by a number or letter code, termed the "revision number," "revision level," or simply "revision."
-
-### RocketChat
-
-An open source chat application for teams, RocketChat is very similar to Slack but it is also open-source.
-
-### Route Table
-
-A route table contains rules (called routes) that determine where network traffic is directed. Each [subnet in a VPC](http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Route_Tables.html) must be associated with a route table.
-
-### Runners
-
-Actual build machines/containers that [run and execute tests](https://gitlab.com/gitlab-org/gitlab-runner) you have specified to be run on GitLab CI.
-
-### Sidekiq
-
-The background job processor GitLab [uses](../../administration/troubleshooting/sidekiq.md) to asynchronously run tasks.
-
-### Software as a service (SaaS)
-
-Software that is hosted centrally and accessed on-demand (i.e. whenever you want to). This applies to GitLab.com.
-
-### Software Configuration Management (SCM)
-
-This term is often used by people when they mean "Version Control."
-
-### Scrum
-
-An Agile [framework](https://www.scrum.org/Resources/What-is-Scrum) designed to typically help complete complex software projects. It's made up of several parts: product requirements backlog, sprint planning, sprint (development), sprint review, and retrospec (analyzing the sprint). The goal is to end up with potentially shippable products.
-
-### Scrum Board
-
-The board used to track the status and progress of each of the sprint backlog items.
-
-### Shell
-
-Terminal on Mac OSX, GitBash on Windows, or Linux Terminal on Linux. You [use git](../../gitlab-basics/start-using-git.md) and make changes to GitLab projects in your shell. You [use git](../../gitlab-basics/start-using-git.md) and make changes to GitLab projects in your shell.
-
-### Shell command runner
-
-### Single-tenant
-
-The tenant purchases their own copy of the software and the software can be customized to meet the specific and needs of that customer. [GitHost.io](https://about.gitlab.com/handbook/positioning-faq/) is our provider of single-tenant 'managed cloud' GitLab instances.
-
-### Slack
-
-Real time messaging app for teams that is used internally by GitLab team members. GitLab users can enable [Slack integration](../../project_services/slack.md) to trigger push, issue, and merge request events among others.
-
-### Slash commands
-
-### Slave Servers
-
-Also known as secondary servers, these help to spread the load over multiple machines. They also provide backups when the master/primary server crashes.
-
-### Source Code
-
-Program code as typed by a computer programmer (i.e. it has not yet been compiled/translated by the computer to machine language).
-
-### Speed Index
-
-[Speed Index](https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/metrics/speed-index) is "the average time at which visible parts of the page are displayed".
-
-### SSH Key
-
-A unique identifier of a computer. It is used to identify computers without the need for a password (e.g., On GitLab I have [added the ssh key](../../gitlab-basics/create-your-ssh-keys.md) of all my work machines so that the GitLab instance knows that it can accept code pushes and pulls from this trusted machines whose keys are I have added.)
-
-### Single Sign On (SSO)
-
-An authentication process that allows you enter one username and password to access multiple applications.
-
-### Staging Area
-
-[Staging occurs](https://git-scm.com/book/en/v2/Getting-Started-Git-Basics) before the commit process in git. The staging area is a file, generally contained in your Git directory, that stores information about what will go into your next commit. It’s sometimes referred to as the “index.""
-
-### Standard Subscription
-
-Our mid range EE subscription that includes 24/7 support and support for High Availability [Standard Subscription](https://about.gitlab.com/pricing/).
-
-### Stash
-
-Atlassian's Git on-premise solution. Think of it as Atlassian's GitLab EE, now known as BitBucket Server.
-
-### Static Site Generators (SSGs)
-
-A [software](https://wiki.python.org/moin/StaticSiteGenerator) that takes some text and templates as input and produces html files on the output.
-
-### Subversion
-
-Non-proprietary, centralized version control system.
-
-### Sudo
-
-A program that allows you to perform superuser/administrator actions on Unix Operating Systems (e.g., Linux, OS X.) It actually stands for 'superuser do.'
-
-### Subversion (SVN)
-
-An open source version control system. Read about [migrating from SVN](../../workflow/importing/migrating_from_svn.md) to GitLab using SubGit.
-
-### Tag
-
-[Represents](../../api/tags.md) a version of a particular branch at a moment in time.
-
-### Tenancy
-
-#### Multi-tenant
-
-A [multi-tenant](http://whatis.techtarget.com/definition/multi-tenancy) GitLab instance can have any number of customers - such as companies or groups of users using it. GitLab.com is an example of a multi-tenant GitLab instance.
-
-#### Single-tenant
-
-A [single-tenant](http://searchcloudapplications.techtarget.com/definition/single-tenancy) GitLab instance has only one customer - such as a company - using it. On premise GitLab instances are almost exclusively single-tenant.
-
-### Tool Stack
-
-The set of tools used in a process to achieve a common outcome (e.g. set of tools used in Application Lifecycle Management).
-
-### Trac
-
-An open source project management and bug tracking web [application](https://trac.edgewall.org/).
-
-### True-Up licensing model
-
-### Ubuntu
-
-### Untracked files
-
-New files that Git has not [been told](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository) to track previously. Add them by using the command "git add [file path]"
-
-### Upstream repository vs. GitLab repository
-
-[External conversation](https://news.ycombinator.com/item?id=12487112)
-
-### User
-
-Anyone interacting with the software.
-
-### Version Control Software (VCS)
-
-Version control is a system that records changes to a file or set of files over time so that you can recall specific versions later. VCS [has evolved](https://docs.google.com/presentation/d/16sX7hUrCZyOFbpvnrAFrg6tVO5_yT98IgdAqOmXwBho/edit#slide=id.gd69537a19_0_32) from local version control systems, to centralized version control systems, to the present [distributed version control systems](https://en.wikipedia.org/wiki/Distributed_version_control) like Git, Mercurial, Bazaar, and Darcs. If any server dies, and these systems were collaborating via it, any of the client repositories can be copied back up to the server to restore it.
-
-### Virtual Private Cloud (VPC)
-
-A [VPC](#virtual-private-cloud-vpc) is an on demand configurable pool of shared computing resources allocated within a public cloud environment, providing some isolation between the different users using the resources. GitLab users need to create a new Amazon VPC in order to [set up High Availability](../../install/aws/index.md).
-
-### Virtual private server (VPS)
-
-A [virtual machine](https://en.wikipedia.org/wiki/Virtual_private_server) sold as a service by an Internet hosting service. A VPS runs its own copy of an operating system, and customers have superuser-level access to that operating system instance, so they can install almost any software that runs on that OS.
-
-### VM Instance
-
-In object-oriented programming, an [instance](http://stackoverflow.com/questions/20461907/what-is-meaning-of-instance-in-programming) is a specific realization of any [object](https://cloud.google.com/compute/docs/instances/). An object may be varied in a number of ways. Each realized variation of that object is an instance. Therefore, a VM instance is an instance of a virtual machine, which is an emulation of a computer system.
-
-### Waterfall
-
-A [model](http://www.umsl.edu/~hugheyd/is6840/waterfall.html) of building software that involves collecting all requirements from the customer, then building and refining all the requirements and finally delivering the complete software to the customer that meets all the requirements they specified.
-
-### Webhooks
-
-A way for an app to [provide](../../user/project/integrations/webhooks.md) other applications with real-time information (e.g., send a message to a slack channel when a commit is pushed.) Read about setting up [custom git hooks](../../administration/custom_hooks.md) for when webhooks are insufficient.
-
-### Wiki
-
-A [website/system](http://www.wiki.com/) that allows for collaborative editing of its content by the users. In programming, wikis usually contain documentation of how to use the software.
-
-### Working area
-
-Files that have been modified but are not committed. Check them by using the command "git status".
-
-### Working Tree
-
-[Consists of files](http://stackoverflow.com/questions/3689838/difference-between-head-working-tree-index-in-git) that you are currently working on.
-
-### YAML
-
-A human-readable data serialization [language](http://www.yaml.org/about.html) that takes concepts from programming languages such as C, Perl, and Python, and ideas from XML and the data format of electronic mail.
+If you are looking for a definition of a specific term, please search these sites.
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index d78cf778110..c65f369244a 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -214,6 +214,159 @@ dependency_scanning:
paths: [gl-dependency-scanning-report.json]
```
+## Reports JSON format
+
+CAUTION: **Caution:**
+The JSON report artifacts are not a public API of Dependency Scanning and their format may change in future.
+
+The Dependency Scanning tool emits a JSON report file. Here is an example of a structure for a report will all important parts of
+it highlighted:
+
+```json-doc
+{
+ "version": "2.0",
+ "vulnerabilities": [
+ {
+ "category": "dependency_scanning",
+ "name": "Regular Expression Denial of Service",
+ "message": "Regular Expression Denial of Service in debug",
+ "description": "The debug module is vulnerable to regular expression denial of service when untrusted user input is passed into the `o` formatter. It takes around 50k characters to block for 2 seconds making this a low severity issue.",
+ "cve": "yarn.lock:debug:gemnasium:37283ed4-0380-40d7-ada7-2d994afcc62a",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest versions.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "yarn.lock",
+ "dependency": {
+ "package": {
+ "name": "debug"
+ },
+ "version": "1.0.5"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-37283ed4-0380-40d7-ada7-2d994afcc62a",
+ "value": "37283ed4-0380-40d7-ada7-2d994afcc62a",
+ "url": "https://deps.sec.gitlab.com/packages/npm/debug/versions/1.0.5/advisories"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://nodesecurity.io/advisories/534"
+ },
+ {
+ "url": "https://github.com/visionmedia/debug/issues/501"
+ },
+ {
+ "url": "https://github.com/visionmedia/debug/pull/504"
+ }
+ ]
+ },
+ {
+ "category": "dependency_scanning",
+ "name": "Authentication bypass via incorrect DOM traversal and canonicalization",
+ "message": "Authentication bypass via incorrect DOM traversal and canonicalization in saml2-js",
+ "description": "Some XML DOM traversal and canonicalization APIs may be inconsistent in handling of comments within XML nodes. Incorrect use of these APIs by some SAML libraries results in incorrect parsing of the inner text of XML nodes such that any inner text after the comment is lost prior to cryptographically signing the SAML message. Text after the comment therefore has no impact on the signature on the SAML message.\r\n\r\nA remote attacker can modify SAML content for a SAML service provider without invalidating the cryptographic signature, which may allow attackers to bypass primary authentication for the affected SAML service provider.",
+ "cve": "yarn.lock:saml2-js:gemnasium:9952e574-7b5b-46fa-a270-aeb694198a98",
+ "severity": "Unknown",
+ "solution": "Upgrade to fixed version.\r\n",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "yarn.lock",
+ "dependency": {
+ "package": {
+ "name": "saml2-js"
+ },
+ "version": "1.5.0"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-9952e574-7b5b-46fa-a270-aeb694198a98",
+ "value": "9952e574-7b5b-46fa-a270-aeb694198a98",
+ "url": "https://deps.sec.gitlab.com/packages/npm/saml2-js/versions/1.5.0/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2017-11429",
+ "value": "CVE-2017-11429",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-11429"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://github.com/Clever/saml2/commit/3546cb61fd541f219abda364c5b919633609ef3d#diff-af730f9f738de1c9ad87596df3f6de84R279"
+ },
+ {
+ "url": "https://github.com/Clever/saml2/issues/127"
+ },
+ {
+ "url": "https://www.kb.cert.org/vuls/id/475445"
+ }
+ ]
+ }
+ ],
+ "remediations": [
+ {
+ "fixes": [
+ {
+ "cve": "yarn.lock:saml2-js:gemnasium:9952e574-7b5b-46fa-a270-aeb694198a98"
+ }
+ ],
+ "summary": "Upgrade saml2-js",
+ "diff": "ZGlmZiAtLWdpdCBhL...OR0d1ZUc2THh3UT09Cg==" // some content is omitted for brevity
+ }
+ ]
+}
+```
+
+Here is the description of the report file structure nodes and their meaning. All fields are mandatory to be present in
+the report JSON unless stated otherwise. Presence of optional fields depends on the underlying analyzers being used.
+
+| Report JSON node | Function |
+|------------------------------------------------------|----------|
+| `version` | Report syntax version used to generate this JSON. |
+| `vulnerabilities` | Array of vulnerability objects. |
+| `vulnerabilities[].category` | Where this vulnerability belongs (SAST, Dependency Scanning etc.). For Dependency Scanning, it will always be `dependency_scanning`. |
+| `vulnerabilities[].name` | Name of the vulnerability, this must not include the occurrence's specific information. Optional. |
+| `vulnerabilities[].message` | A short text that describes the vulnerability, it may include occurrence's specific information. Optional. |
+| `vulnerabilities[].description` | A long text that describes the vulnerability. Optional. |
+| `vulnerabilities[].cve` | A fingerprint string value that represents a concrete occurrence of the vulnerability. It's used to determine whether two vulnerability occurrences are same or different. May not be 100% accurate. **This is NOT a [CVE](https://cve.mitre.org/)**. |
+| `vulnerabilities[].severity` | How much the vulnerability impacts the software. Possible values: `Undefined` (an analyzer has not provided this info), `Info`, `Unknown`, `Low`, `Medium`, `High`, `Critical`. |
+| `vulnerabilities[].confidence` | How reliable the vulnerability's assessment is. Possible values: `Undefined` (an analyzer has not provided this info), `Ignore`, `Unknown`, `Experimental`, `Low`, `Medium`, `High`, `Confirmed`. |
+| `vulnerabilities[].solution` | Explanation of how to fix the vulnerability. Optional. |
+| `vulnerabilities[].scanner` | A node that describes the analyzer used find this vulnerability. |
+| `vulnerabilities[].scanner.id` | Id of the scanner as a snake_case string. |
+| `vulnerabilities[].scanner.name` | Name of the scanner, for display purposes. |
+| `vulnerabilities[].location` | A node that tells which class and/or method is affected by the vulnerability. |
+| `vulnerabilities[].location.file` | Path to the dependencies file (e.g., `yarn.lock`). Optional. |
+| `vulnerabilities[].location.dependency` | A node that describes the dependency of a project where the vulnerability is located. |
+| `vulnerabilities[].location.dependency.package` | A node that provides the information on the package where the vulnerability is located. |
+| `vulnerabilities[].location.dependency.package.name` | Name of the package where the vulnerability is located. Optional. |
+| `vulnerabilities[].location.dependency.version` | Version of the vulnerable package. Optional. |
+| `vulnerabilities[].identifiers` | An ordered array of references that identify a vulnerability on internal or external DBs. |
+| `vulnerabilities[].identifiers[].type` | Type of the identifier. Possible values: common identifier types (among `cve`, `cwe`, `osvdb`, and `usn`) or analyzer-dependent ones (e.g. `gemnasium` for [Gemnasium](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/)). |
+| `vulnerabilities[].identifiers[].name` | Name of the identifier for display purpose. |
+| `vulnerabilities[].identifiers[].value` | Value of the identifier for matching purpose. |
+| `vulnerabilities[].identifiers[].url` | URL to identifier's documentation. Optional. |
+| `vulnerabilities[].links` | An array of references to external documentation pieces or articles that describe the vulnerability further. Optional. |
+| `vulnerabilities[].links[].name` | Name of the vulnerability details link. Optional. |
+| `vulnerabilities[].links[].url` | URL of the vulnerability details document. Optional. |
+| `remediations` | An array of objects containing information on cured vulnerabilities along with patch diffs to apply. |
+| `remediations[].fixes` | An array of strings that represent references to vulnerabilities fixed by this particular remediation. |
+| `remediations[].fixes[].cve` | A string value that describes a fixed vulnerability occurrence in the same format as `vulnerabilities[].cve`. |
+| `remediations[].summary` | Overview of how the vulnerabilities have been fixed. |
+| `remediations[].diff` | base64-encoded remediation code diff, compatible with [`git apply`](https://git-scm.com/docs/git-format-patch#_discussion). |
+
## Security Dashboard
The Security Dashboard is a good place to get an overview of all the security
diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md
index db328262aba..19befb04b76 100644
--- a/doc/user/application_security/sast/index.md
+++ b/doc/user/application_security/sast/index.md
@@ -191,7 +191,7 @@ sast:
You can supply many other [settings variables](https://gitlab.com/gitlab-org/security-products/sast#settings)
via `docker run --env` to customize your job execution.
-## Manual job definition for GitLab 11.4 and earlier (deprecated)
+### Manual job definition for GitLab 11.4 and earlier (deprecated)
CAUTION: **Deprecated:**
Before GitLab 11.5, the SAST job and artifact had to be named specifically
@@ -221,6 +221,118 @@ sast:
paths: [gl-sast-report.json]
```
+## Reports JSON format
+
+CAUTION: **Caution:**
+The JSON report artifacts are not a public API of SAST and their format may change in the future.
+
+The SAST tool emits a JSON report report file. Here is an example of a structure for a report will all important parts of
+it highlighted:
+
+```json-doc
+{
+ "version": "2.0",
+ "vulnerabilities": [
+ {
+ "category": "sast",
+ "name": "Predictable pseudorandom number generator",
+ "message": "Predictable pseudorandom number generator",
+ "description": "The use of java.util.Random is predictable",
+ "cve": "818bf5dacb291e15d9e6dc3c5ac32178:PREDICTABLE_RANDOM",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/groovy/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 47,
+ "end_line": 47,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "generateSecretToken2",
+ "dependency": {
+ "package": {}
+ }
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-PREDICTABLE_RANDOM",
+ "value": "PREDICTABLE_RANDOM",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-330",
+ "value": "330",
+ "url": "https://cwe.mitre.org/data/definitions/330.html"
+ }
+ ]
+ },
+ {
+ "category": "sast",
+ // "name" may be omitted because it could be not reported by a particular analyzer
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:4ad6d4c40a8c263fc265f3384724014e0a4f8dd6200af83e51ff120420038031:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 10,
+ "end_line": 10,
+ "dependency": {
+ "package": {}
+ }
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B108",
+ "value": "B108",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
+ }
+ ]
+ },
+ ],
+ "remediations": []
+}
+```
+
+Here is the description of the report file structure nodes and their meaning. All fields are mandatory to be present in
+the report JSON unless stated otherwise. Presence of optional fields depends on the underlying analyzers being used.
+
+| Report JSON node | Function |
+|-----------------------------------------|----------|
+| `version` | Report syntax version used to generate this JSON. |
+| `vulnerabilities` | Array of vulnerability objects. |
+| `vulnerabilities[].category` | Where this vulnerability belongs (SAST, Dependency Scanning etc.). For SAST, it will always be `sast`. |
+| `vulnerabilities[].name` | Name of the vulnerability, this must not include the occurrence's specific information. Optional. |
+| `vulnerabilities[].message` | A short text that describes the vulnerability, it may include the occurrence's specific information. Optional. |
+| `vulnerabilities[].description` | A long text that describes the vulnerability. Optional. |
+| `vulnerabilities[].cve` | A fingerprint string value that represents a concrete occurrence of the vulnerability. Is used to determine whether two vulnerability occurrences are same or different. May not be 100% accurate. **This is NOT a [CVE](https://cve.mitre.org/)**. |
+| `vulnerabilities[].severity` | How much the vulnerability impacts the software. Possible values: `Undefined` (an analyzer has not provided this info), `Info`, `Unknown`, `Low`, `Medium`, `High`, `Critical`. |
+| `vulnerabilities[].confidence` | How reliable the vulnerability's assessment is. Possible values: `Undefined` (an analyzer has not provided this info), `Ignore`, `Unknown`, `Experimental`, `Low`, `Medium`, `High`, `Confirmed`. |
+| `vulnerabilities[].solution` | Explanation of how to fix the vulnerability. Optional. |
+| `vulnerabilities[].scanner` | A node that describes the analyzer used find this vulnerability. |
+| `vulnerabilities[].scanner.id` | Id of the scanner as a snake_case string. |
+| `vulnerabilities[].scanner.name` | Name of the scanner, for display purposes. |
+| `vulnerabilities[].location` | A node that tells which class and/or method is affected by the vulnerability. |
+| `vulnerabilities[].location.file` | Path to the file where the vulnerability is located. Optional. |
+| `vulnerabilities[].location.start_line` | The first line of the code affected by the vulnerability. Optional. |
+| `vulnerabilities[].location.end_line` | The last line of the code affected by the vulnerability. Optional. |
+| `vulnerabilities[].location.class` | If specified, provides the name of the class where the vulnerability is located. Optional. |
+| `vulnerabilities[].location.method` | If specified, provides the name of the method where the vulnerability is located. Optional. |
+| `vulnerabilities[].identifiers` | An ordered array of references that identify a vulnerability on internal or external DBs. |
+| `vulnerabilities[].identifiers[].type` | Type of the identifier. Possible values: common identifier types (among `cve`, `cwe`, `osvdb`, and `usn`) or analyzer-dependent ones (e.g., `bandit_test_id` for [Bandit analyzer](https://wiki.openstack.org/wiki/Security/Projects/Bandit)). |
+| `vulnerabilities[].identifiers[].name` | Name of the identifier for display purposes. |
+| `vulnerabilities[].identifiers[].value` | Value of the identifier for matching purposes. |
+| `vulnerabilities[].identifiers[].url` | URL to identifier's documentation. Optional. |
+
## Secret detection
GitLab is also able to detect secrets and credentials that have been unintentionally pushed to the repository.
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index 8335e532d0b..97d309caf7c 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -113,6 +113,8 @@ Add the following information:
1. Optionally, choose an avatar for your group.
1. Choose the [visibility level](../../public_access/public_access.md).
+For more details on creating groups, watch the video [GitLab Namespaces (users, groups and subgroups)](https://youtu.be/r0sJgjR2f5A).
+
## Add users to a group
A benefit of putting multiple projects in one group is that you can
@@ -215,10 +217,8 @@ Get an overview of the vulnerabilities of all the projects in a group and its su
## Insights **[ULTIMATE]**
-> Introduced in [GitLab Ultimate][ee] 11.9 behind the `insights` feature flag.
-
-Configure the Insights that matter for your groups or projects, allowing users to explore data
-such as:
+Configure the Insights that matter for your groups or projects, allowing users
+to explore data such as:
- Triage hygiene
- Issues created/closed per a given period
@@ -232,8 +232,8 @@ such as:
From GitLab 10.5, you can transfer groups in the following ways:
- Transfer a subgroup to a new parent group.
-- Convert a top-level group into a subgroup by transfering it to the desired group.
-- Convert a subgroup into a top-level group by transfering it out of its current group.
+- Convert a top-level group into a subgroup by transferring it to the desired group.
+- Convert a subgroup into a top-level group by transferring it out of its current group.
When transferring groups, note:
diff --git a/doc/user/group/insights/index.md b/doc/user/group/insights/index.md
index a4ea71074ec..1aba5d0986b 100644
--- a/doc/user/group/insights/index.md
+++ b/doc/user/group/insights/index.md
@@ -5,11 +5,7 @@ type: reference, howto
# Insights **[ULTIMATE]**
> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.9 behind the `insights` feature flag.
-
-CAUTION: **Beta:**
-Insights is considered beta, and is not ready for production use.
-Follow [gitlab-org/quality/team-tasks#137](https://gitlab.com/gitlab-org/quality/team-tasks/issues/137#general-availability)
-for updates.
+> **Generally Available** (GA) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0.
Configure the Insights that matter for your groups to explore data such as
triage hygiene, issues created/closed per a given period, average time for merge
diff --git a/doc/user/instance_statistics/convdev.md b/doc/user/instance_statistics/convdev.md
index 2c9e0ecbf65..d486ecc39a4 100644
--- a/doc/user/instance_statistics/convdev.md
+++ b/doc/user/instance_statistics/convdev.md
@@ -5,7 +5,7 @@
NOTE: **Note:**
Your GitLab instance's [usage ping](../admin_area/settings/usage_statistics.md#usage-ping-core-only) must be activated in order to use this feature.
-The Conversational Development Index (ConvDev Index) gives you an overview of your entire
+The [Conversational Development](http://conversationaldevelopment.com/2017/04/16/what-is-conversational-development/) Index (ConvDev Index) gives you an overview of your entire
instance's adoption of [Concurrent DevOps](https://about.gitlab.com/concurrent-devops/)
from planning to monitoring.
diff --git a/doc/user/project/cycle_analytics.md b/doc/user/project/cycle_analytics.md
index 19ab911e39f..dc97a44fd68 100644
--- a/doc/user/project/cycle_analytics.md
+++ b/doc/user/project/cycle_analytics.md
@@ -1,10 +1,7 @@
# Cycle Analytics
-> [Introduced][ce-5986] in GitLab 8.12. Further features were added in GitLab
- 8.14.
-
-Cycle Analytics measures the time spent to go from an [idea to production] for
-each of your projects. Cycle Analytics displays the median time for an idea to
+Cycle Analytics measures the time spent to go from an [idea to production] - also known
+as cycle time - for each of your projects. Cycle Analytics displays the median time for an idea to
reach production, along with the time typically spent in each DevOps stage along the way.
Cycle Analytics is useful in order to quickly determine the velocity of a given
@@ -54,9 +51,9 @@ Below you can see in more detail what the various stages of Cycle Analytics mean
| Issue | Measures the median time between creating an issue and taking action to solve it, by either labeling it or adding it to a milestone, whatever comes first. The label will be tracked only if it already has an [Issue Board list][board] created for it. |
| Plan | Measures the median time between the action you took for the previous stage, and pushing the first commit to the branch. The very first commit of the branch is the one that triggers the separation between **Plan** and **Code**, and at least one of the commits in the branch needs to contain the related issue number (e.g., `#42`). If none of the commits in the branch mention the related issue number, it is not considered to the measurement time of the stage. |
| Code | Measures the median time between pushing a first commit (previous stage) and creating a merge request (MR) related to that commit. The key to keep the process tracked is to include the [issue closing pattern] to the description of the merge request (for example, `Closes #xxx`, where `xxx` is the number of the issue related to this merge request). If the issue closing pattern is not present in the merge request description, the MR is not considered to the measurement time of the stage. |
-| Test | Measures the median time to run the entire pipeline for that project. It's related to the time GitLab CI takes to run every job for the commits pushed to that merge request defined in the previous stage. It is basically the start->finish time for all pipelines. `master` is not excluded. It does not attempt to track time for any particular stages. |
-| Review | Measures the median time taken to review the merge request, between its creation and until it's merged. |
-| Staging | Measures the median time between merging the merge request until the very first deployment to production. It's tracked by the [environment] set to `production` or matching `production/*` (case-sensitive, `Production` won't work) in your GitLab CI configuration. If there isn't a production environment, this is not tracked. |
+| Test | Measures the median time to run the entire pipeline for that project. It's related to the time GitLab CI takes to run every job for the commits pushed to that merge request defined in the previous stage. It is basically the start->finish time for all pipelines. |
+| Review | Measures the median time taken to review the merge request that has closing issue pattern, between its creation and until it's merged. |
+| Staging | Measures the median time between merging the merge request with closing issue pattern until the very first deployment to production. It's tracked by the [environment] set to `production` or matching `production/*` (case-sensitive, `Production` won't work) in your GitLab CI configuration. If there isn't a production environment, this is not tracked. |
| Production| The sum of all time (medians) taken to run the entire process, from issue creation to deploying the code to production. |
---
@@ -77,8 +74,7 @@ To sum up, anything that doesn't follow the [GitLab flow] won't be tracked at al
So, the Cycle Analytics dashboard won't present any data:
- For merge requests that do not close an issue.
-- For issues not labeled with a label present in the Issue Board.
-- For issues not assigned a milestone.
+- For issues not labeled with a label present in the Issue Board or for issues not assigned a milestone.
- For staging and production stages, if the project has no `production` or `production/*`
environment.
@@ -86,7 +82,7 @@ So, the Cycle Analytics dashboard won't present any data:
Below is a simple fictional workflow of a single cycle that happens in a
single day passing through all seven stages. Note that if a stage does not have
-a start/stop mark, it is not measured and hence not calculated in the median
+a start and a stop mark, it is not measured and hence not calculated in the median
time. It is assumed that milestones are created and CI for testing and setting
environments is configured.
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index 8fba892594b..e194d57e2e0 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -60,6 +60,8 @@ For additional technical details, you can refer to the
[GitHub Importer](../../../development/github_importer.md "Working with the GitHub importer")
developer documentation.
+For an overview of the import process, see the video [Migrating from GitHub to GitLab](https://youtu.be/VYOXuOg9tQI).
+
## Import your GitHub repository into GitLab
### Using the GitHub integration
diff --git a/doc/user/project/index.md b/doc/user/project/index.md
index a24f525253d..587b4121e4e 100644
--- a/doc/user/project/index.md
+++ b/doc/user/project/index.md
@@ -84,6 +84,7 @@ When you create a project in GitLab, you'll have access to a large number of
- [Wiki](wiki/index.md): document your GitLab project in an integrated Wiki.
- [Snippets](../snippets.md): store, share and collaborate on code snippets.
- [Cycle Analytics](cycle_analytics.md): review your development lifecycle.
+- [Insights](insights/index.md): configure the Insights that matter for your projects. **[ULTIMATE]**
- [Security Dashboard](security_dashboard.md): Security Dashboard. **[ULTIMATE]**
- [Syntax highlighting](highlighting.md): an alternative to customize
your code blocks, overriding GitLab's default choice of language.
diff --git a/doc/user/project/insights/index.md b/doc/user/project/insights/index.md
index 3344e560870..2e2a27f112e 100644
--- a/doc/user/project/insights/index.md
+++ b/doc/user/project/insights/index.md
@@ -1,11 +1,7 @@
# Insights **[ULTIMATE]**
> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.9 behind the `insights` feature flag.
-
-CAUTION: **Beta:**
-Insights is considered beta, and is not ready for production use.
-Follow [gitlab-org/quality/team-tasks#137](https://gitlab.com/gitlab-org/quality/team-tasks/issues/137#general-availability)
-for updates.
+> **Generally Available** (GA) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0.
Configure the Insights that matter for your projects to explore data such as
triage hygiene, issues created/closed per a given period, average time for merge
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index e3502a632d9..ba890c5ac01 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -26,6 +26,12 @@ Set up your project's access, [visibility](../../../public_access/public_access.
![projects sharing permissions](img/sharing_and_permissions_settings.png)
+If Issues are disabled, or you can't access Issues because you're not a project member, then Lables and Milestones
+links will be missing from the sidebar UI.
+
+You can still access them with direct links if you can access Merge Requests. This is deliberate, if you can see
+Issues or Merge Requests, both of which use Labels and Milestones, then you shouldn't be denied access to Labels and Milestones pages.
+
### Issue settings
Add an [issue description template](../description_templates.md#description-templates) to your project, so that every new issue will start with a custom template.
diff --git a/doc/workflow/gitlab_flow.md b/doc/workflow/gitlab_flow.md
index 7d0abb93262..3e24557591c 100644
--- a/doc/workflow/gitlab_flow.md
+++ b/doc/workflow/gitlab_flow.md
@@ -27,6 +27,8 @@ People have a hard time figuring out which branch has the latest code, or which
Frequently, the reaction to this problem is to adopt a standardized pattern such as [Git flow](https://nvie.com/posts/a-successful-git-branching-model/) and [GitHub flow](http://scottchacon.com/2011/08/31/github-flow.html).
We think there is still room for improvement. In this document, we describe a set of practices we call GitLab flow.
+For a video introduction of how this works in GitLab, see [GitLab Flow](https://youtu.be/InKNIvky2KE).
+
## Git flow and its problems
![Git Flow timeline by Vincent Driessen, used with permission](gitdashflow.png)
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 880b07d0a84..8840accf675 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -265,6 +265,7 @@ module API
expose :open_issues_count, if: lambda { |project, options| project.feature_available?(:issues, options[:current_user]) }
expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] }
+ expose :ci_default_git_depth
expose :public_builds, as: :public_jobs
expose :ci_config_path, if: -> (project, options) { Ability.allowed?(options[:current_user], :download_code, project) }
expose :shared_with_groups do |project, options|
@@ -287,6 +288,7 @@ module API
# N+1 is solved then by using `subject.tags.map(&:name)`
# MR describing the solution: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20555
super(projects_relation).preload(:group)
+ .preload(:ci_cd_settings)
.preload(project_group_links: { group: :route },
fork_network: :root_project,
fork_network_member: :forked_from_project,
diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb
index 813e46e9520..f242f1fea0e 100644
--- a/lib/api/helpers/projects_helpers.rb
+++ b/lib/api/helpers/projects_helpers.rb
@@ -29,6 +29,7 @@ module API
optional :merge_method, type: String, values: %w(ff rebase_merge merge), desc: 'The merge method used when merging merge requests'
optional :initialize_with_readme, type: Boolean, desc: "Initialize a project with a README.md"
optional :external_authorization_classification_label, type: String, desc: 'The classification label for the project'
+ optional :ci_default_git_depth, type: Integer, desc: 'Default number of revisions for shallow cloning'
end
params :optional_project_params_ee do
diff --git a/lib/gitlab/ci/templates/Serverless.gitlab-ci.yml b/lib/gitlab/ci/templates/Serverless.gitlab-ci.yml
index 3f46bb89e94..a3db2705bf6 100644
--- a/lib/gitlab/ci/templates/Serverless.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Serverless.gitlab-ci.yml
@@ -14,7 +14,7 @@ stages:
.serverless:deploy:image:
stage: deploy
- image: gcr.io/triggermesh/tm@sha256:3cfdd470a66b741004fb02354319d79f1598c70117ce79978d2e07e192bfb336 # v0.0.11
+ image: gcr.io/triggermesh/tm@sha256:3cfdd470a66b741004fb02354319d79f1598c70117ce79978d2e07e192bfb336 # v0.0.11
environment: development
script:
- echo "$CI_REGISTRY_IMAGE"
diff --git a/lib/gitlab/cluster/rack_timeout_observer.rb b/lib/gitlab/cluster/rack_timeout_observer.rb
new file mode 100644
index 00000000000..5182b2be148
--- /dev/null
+++ b/lib/gitlab/cluster/rack_timeout_observer.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Cluster
+ class RackTimeoutObserver
+ TRANSITION_STATES = %i(ready active).freeze
+
+ def initialize
+ @counter = Gitlab::Metrics.counter(:rack_requests_total, 'Number of requests in a given rack state')
+ end
+
+ # returns the Proc to be used as the observer callback block
+ def callback
+ method(:log_timeout_exception)
+ end
+
+ private
+
+ def log_timeout_exception(env)
+ info = env[::Rack::Timeout::ENV_INFO_KEY]
+ return unless info
+ return if TRANSITION_STATES.include?(info.state)
+
+ @counter.increment(labels(info, env))
+ end
+
+ def labels(info, env)
+ params = controller_params(env) || grape_params(env) || {}
+
+ {
+ controller: params['controller'],
+ action: params['action'],
+ route: params['route'],
+ state: info.state
+ }
+ end
+
+ def controller_params(env)
+ env['action_dispatch.request.parameters']
+ end
+
+ def grape_params(env)
+ endpoint = env[Grape::Env::API_ENDPOINT]
+ route = endpoint&.route&.pattern&.origin
+ return unless route
+
+ { 'route' => route }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/loaders/batch_commit_loader.rb b/lib/gitlab/graphql/loaders/batch_lfs_oid_loader.rb
index f410c3195f8..8f34e58a771 100644
--- a/lib/gitlab/graphql/loaders/batch_commit_loader.rb
+++ b/lib/gitlab/graphql/loaders/batch_lfs_oid_loader.rb
@@ -3,7 +3,7 @@
module Gitlab
module Graphql
module Loaders
- class BatchCommitLoader
+ class BatchLfsOidLoader
def initialize(repository, blob_id)
@repository, @blob_id = repository, blob_id
end
diff --git a/lib/gitlab/rack_timeout_observer.rb b/lib/gitlab/rack_timeout_observer.rb
deleted file mode 100644
index 80d3f7dea60..00000000000
--- a/lib/gitlab/rack_timeout_observer.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- class RackTimeoutObserver
- def initialize
- @counter = Gitlab::Metrics.counter(:rack_state_total, 'Number of requests in a given rack state')
- end
-
- # returns the Proc to be used as the observer callback block
- def callback
- method(:log_timeout_exception)
- end
-
- private
-
- def log_timeout_exception(env)
- info = env[::Rack::Timeout::ENV_INFO_KEY]
- return unless info
-
- @counter.increment(labels(info, env))
- end
-
- def labels(info, env)
- params = controller_params(env) || grape_params(env) || {}
-
- {
- controller: params['controller'],
- action: params['action'],
- route: params['route'],
- state: info.state
- }
- end
-
- def controller_params(env)
- env['action_dispatch.request.parameters']
- end
-
- def grape_params(env)
- endpoint = env[Grape::Env::API_ENDPOINT]
- route = endpoint&.route&.pattern&.origin
- return unless route
-
- { 'route' => route }
- end
- end
-end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 20c8a834d04..88ace6057cf 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -6045,6 +6045,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -12408,9 +12411,6 @@ msgstr ""
msgid "mrWidget|The source branch will not be deleted"
msgstr ""
-msgid "mrWidget|The target branch has advanced, which invalidates the merge request pipeline. Please update the source branch and retry merging"
-msgstr ""
-
msgid "mrWidget|There are merge conflicts"
msgstr ""
diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
index 86ba5e819ba..5ca9ddb6b19 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
@@ -9,7 +9,8 @@ module QA
Page::Main::Login.perform(&:sign_in_using_credentials)
end
- describe 'Auto DevOps support', :orchestrated, :kubernetes do
+ # Failure issue: https://gitlab.com/gitlab-org/quality/nightly/issues/108
+ describe 'Auto DevOps support', :orchestrated, :kubernetes, :quarantine do
context 'when rbac is enabled' do
before(:all) do
@cluster = Service::KubernetesCluster.new.create!
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index f8c0ab55eb4..34cbf0c8723 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -412,7 +412,7 @@ describe Projects::MergeRequestsController do
end
end
- context 'when the pipeline succeeds is passed' do
+ context 'when merge when pipeline succeeds option is passed' do
let!(:head_pipeline) do
create(:ci_empty_pipeline, project: project, sha: merge_request.diff_head_sha, ref: merge_request.source_branch, head_pipeline_of: merge_request)
end
@@ -462,6 +462,30 @@ describe Projects::MergeRequestsController do
expect(json_response).to eq('status' => 'merge_when_pipeline_succeeds')
end
end
+
+ context 'when auto merge has not been enabled yet' do
+ it 'calls AutoMergeService#execute' do
+ expect_next_instance_of(AutoMergeService) do |service|
+ expect(service).to receive(:execute).with(merge_request, 'merge_when_pipeline_succeeds')
+ end
+
+ merge_when_pipeline_succeeds
+ end
+ end
+
+ context 'when auto merge has already been enabled' do
+ before do
+ merge_request.update!(auto_merge_enabled: true, merge_user: user)
+ end
+
+ it 'calls AutoMergeService#update' do
+ expect_next_instance_of(AutoMergeService) do |service|
+ expect(service).to receive(:update).with(merge_request)
+ end
+
+ merge_when_pipeline_succeeds
+ end
+ end
end
describe 'only_allow_merge_if_all_discussions_are_resolved? setting' do
diff --git a/spec/controllers/projects/settings/ci_cd_controller_spec.rb b/spec/controllers/projects/settings/ci_cd_controller_spec.rb
index 117b9cf7915..5bfbcf6eeb5 100644
--- a/spec/controllers/projects/settings/ci_cd_controller_spec.rb
+++ b/spec/controllers/projects/settings/ci_cd_controller_spec.rb
@@ -212,7 +212,7 @@ describe Projects::Settings::CiCdController do
subject
project.reload
- expect(project.default_git_depth).to eq(10)
+ expect(project.ci_default_git_depth).to eq(10)
end
end
end
diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb
index 2adeb37c98a..e6f44aa7d20 100644
--- a/spec/features/commits_spec.rb
+++ b/spec/features/commits_spec.rb
@@ -82,7 +82,7 @@ describe 'Commits' do
it 'shows pipeline`s data' do
expect(page).to have_content pipeline.sha[0..7]
- expect(page).to have_content pipeline.git_commit_message
+ expect(page).to have_content pipeline.git_commit_message.gsub!(/\s+/, ' ')
expect(page).to have_content pipeline.user.name
end
end
@@ -125,7 +125,7 @@ describe 'Commits' do
it 'Renders header', :js do
expect(page).to have_content pipeline.sha[0..7]
- expect(page).to have_content pipeline.git_commit_message
+ expect(page).to have_content pipeline.git_commit_message.gsub!(/\s+/, ' ')
expect(page).to have_content pipeline.user.name
expect(page).not_to have_link('Cancel running')
expect(page).not_to have_link('Retry')
@@ -147,7 +147,7 @@ describe 'Commits' do
it do
expect(page).to have_content pipeline.sha[0..7]
- expect(page).to have_content pipeline.git_commit_message
+ expect(page).to have_content pipeline.git_commit_message.gsub!(/\s+/, ' ')
expect(page).to have_content pipeline.user.name
expect(page).not_to have_link('Cancel running')
diff --git a/spec/features/ics/dashboard_issues_spec.rb b/spec/features/ics/dashboard_issues_spec.rb
index debae0ea930..b74bbf848ac 100644
--- a/spec/features/ics/dashboard_issues_spec.rb
+++ b/spec/features/ics/dashboard_issues_spec.rb
@@ -91,7 +91,7 @@ describe 'Dashboard Issues Calendar Feed' do
expect(body).to have_text("SUMMARY:test title (in #{project.full_path})")
# line length for ics is 75 chars
- expected_description = "DESCRIPTION:Find out more at #{issue_url(issue)}".insert(75, "\r\n")
+ expected_description = "DESCRIPTION:Find out more at #{issue_url(issue)}".insert(75, ' ')
expect(body).to have_text(expected_description)
expect(body).to have_text("DTSTART;VALUE=DATE:#{Date.tomorrow.strftime('%Y%m%d')}")
expect(body).to have_text("URL:#{issue_url(issue)}")
diff --git a/spec/features/ics/group_issues_spec.rb b/spec/features/ics/group_issues_spec.rb
index 4177c7f8704..86da720c8be 100644
--- a/spec/features/ics/group_issues_spec.rb
+++ b/spec/features/ics/group_issues_spec.rb
@@ -66,7 +66,7 @@ describe 'Group Issues Calendar Feed' do
expect(body).to have_text("SUMMARY:test title (in #{project.full_path})")
# line length for ics is 75 chars
- expected_description = "DESCRIPTION:Find out more at #{issue_url(issue)}".insert(75, "\r\n")
+ expected_description = "DESCRIPTION:Find out more at #{issue_url(issue)}".insert(75, ' ')
expect(body).to have_text(expected_description)
expect(body).to have_text("DTSTART;VALUE=DATE:#{Date.tomorrow.strftime('%Y%m%d')}")
expect(body).to have_text("URL:#{issue_url(issue)}")
diff --git a/spec/features/ics/project_issues_spec.rb b/spec/features/ics/project_issues_spec.rb
index 0d9844be099..37b90c666bc 100644
--- a/spec/features/ics/project_issues_spec.rb
+++ b/spec/features/ics/project_issues_spec.rb
@@ -65,7 +65,7 @@ describe 'Project Issues Calendar Feed' do
expect(body).to have_text("SUMMARY:test title (in #{project.full_path})")
# line length for ics is 75 chars
- expected_description = "DESCRIPTION:Find out more at #{issue_url(issue)}".insert(75, "\r\n")
+ expected_description = "DESCRIPTION:Find out more at #{issue_url(issue)}".insert(75, ' ')
expect(body).to have_text(expected_description)
expect(body).to have_text("DTSTART;VALUE=DATE:#{Date.tomorrow.strftime('%Y%m%d')}")
expect(body).to have_text("URL:#{issue_url(issue)}")
diff --git a/spec/features/merge_request/user_accepts_merge_request_spec.rb b/spec/features/merge_request/user_accepts_merge_request_spec.rb
index 5fa23dbb998..3d029ccec1a 100644
--- a/spec/features/merge_request/user_accepts_merge_request_spec.rb
+++ b/spec/features/merge_request/user_accepts_merge_request_spec.rb
@@ -15,8 +15,7 @@ describe 'User accepts a merge request', :js do
click_button('Merge')
- expect(page).to have_content("The changes were merged into #{merge_request.target_branch} with \
- #{merge_request.short_merge_commit_sha}")
+ expect(page).to have_content("The changes were merged into #{merge_request.target_branch} with #{merge_request.short_merge_commit_sha}")
end
context 'with removing the source branch' do
diff --git a/spec/features/merge_request/user_creates_image_diff_notes_spec.rb b/spec/features/merge_request/user_creates_image_diff_notes_spec.rb
index 5db54f42264..3a9a06a6bc3 100644
--- a/spec/features/merge_request/user_creates_image_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_creates_image_diff_notes_spec.rb
@@ -313,7 +313,7 @@ describe 'Merge request > User creates image diff notes', :js do
def create_image_diff_note
expand_text = 'Click to expand it.'
- page.all('a', text: expand_text).each do |element|
+ page.all('a', text: expand_text, wait: false).each do |element|
element.click
end
diff --git a/spec/features/merge_request/user_sees_diff_spec.rb b/spec/features/merge_request/user_sees_diff_spec.rb
index 04b07525919..8dc5912b8be 100644
--- a/spec/features/merge_request/user_sees_diff_spec.rb
+++ b/spec/features/merge_request/user_sees_diff_spec.rb
@@ -43,8 +43,7 @@ describe 'Merge request > User sees diff', :js do
visit diffs_project_merge_request_path(project, merge_request)
page.within('.alert') do
- expect(page).to have_text("Too many changes to show. Plain diff Email patch To preserve
- performance only 3 of 3+ files are displayed.")
+ expect(page).to have_text("Too many changes to show. Plain diff Email patch To preserve performance only 3 of 3+ files are displayed.")
end
end
end
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index 0066e985fbb..393077a916f 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -565,7 +565,7 @@ describe 'Merge request > User sees merge widget', :js do
click_button 'subtractTest'
expect(page).to have_content('6.66')
- expect(page).to have_content(sample_java_failed_message)
+ expect(page).to have_content(sample_java_failed_message.gsub!(/\s+/, ' ').strip)
end
end
end
@@ -610,7 +610,7 @@ describe 'Merge request > User sees merge widget', :js do
click_button 'Test#sum when a is 2 and b is 2 returns summary'
expect(page).to have_content('2.22')
- expect(page).to have_content(sample_rspec_failed_message)
+ expect(page).to have_content(sample_rspec_failed_message.gsub!(/\s+/, ' ').strip)
end
end
end
diff --git a/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb b/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb
index 04c7f4b6c76..780de76d2c5 100644
--- a/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb
+++ b/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb
@@ -7,8 +7,8 @@ describe 'User comments on a diff', :js do
include RepoHelpers
def expect_suggestion_has_content(element, expected_changing_content, expected_suggested_content)
- changing_content = element.all(:css, '.line_holder.old').map(&:text)
- suggested_content = element.all(:css, '.line_holder.new').map(&:text)
+ changing_content = element.all(:css, '.line_holder.old').map { |el| el.text(normalize_ws: true) }
+ suggested_content = element.all(:css, '.line_holder.new').map { |el| el.text(normalize_ws: true) }
expect(changing_content).to eq(expected_changing_content)
expect(suggested_content).to eq(expected_suggested_content)
diff --git a/spec/features/projects/commits/user_browses_commits_spec.rb b/spec/features/projects/commits/user_browses_commits_spec.rb
index 953517cdff9..a84fee34669 100644
--- a/spec/features/projects/commits/user_browses_commits_spec.rb
+++ b/spec/features/projects/commits/user_browses_commits_spec.rb
@@ -13,7 +13,7 @@ describe 'User browses commits' do
it 'renders commit' do
visit project_commit_path(project, sample_commit.id)
- expect(page).to have_content(sample_commit.message)
+ expect(page).to have_content(sample_commit.message.gsub!(/\s+/, ' '))
.and have_content("Showing #{sample_commit.files_changed_count} changed files")
.and have_content('Side-by-side')
end
diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb
index ab16fdee883..254e885ce46 100644
--- a/spec/features/projects/features_visibility_spec.rb
+++ b/spec/features/projects/features_visibility_spec.rb
@@ -68,7 +68,8 @@ describe 'Edit Project Settings' do
end
it "hides builds when disabled" do
- allow(Ability).to receive(:allowed?).with(member, :read_builds, project).and_return(false)
+ allow(Ability).to receive(:allowed?).and_return(true)
+ allow(Ability).to receive(:allowed?).with(member, :read_build, project).and_return(false)
visit project_pipelines_path(project)
diff --git a/spec/features/projects/files/undo_template_spec.rb b/spec/features/projects/files/undo_template_spec.rb
index fa785ed10ef..91618145391 100644
--- a/spec/features/projects/files/undo_template_spec.rb
+++ b/spec/features/projects/files/undo_template_spec.rb
@@ -50,7 +50,7 @@ end
def check_content_reverted(template_content)
find('.template-selectors-undo-menu .btn-info').click
expect(page).not_to have_content(template_content)
- expect(find('.template-type-selector .dropdown-toggle-text')).to have_content
+ expect(page).to have_css('.template-type-selector .dropdown-toggle-text')
end
def select_file_template(template_selector_selector, template_name)
diff --git a/spec/features/projects/files/user_creates_files_spec.rb b/spec/features/projects/files/user_creates_files_spec.rb
index 69f8bd4d319..264b288ab38 100644
--- a/spec/features/projects/files/user_creates_files_spec.rb
+++ b/spec/features/projects/files/user_creates_files_spec.rb
@@ -174,7 +174,6 @@ describe 'Projects > Files > User creates files' do
it 'creates and commit new file in forked project', :js do
expect(page).to have_selector('.file-editor')
- expect(page).to have_content
find('#editor')
execute_script("ace.edit('editor').setValue('*.rbca')")
diff --git a/spec/features/projects/labels/user_removes_labels_spec.rb b/spec/features/projects/labels/user_removes_labels_spec.rb
index c231e54decd..7f49ddf560f 100644
--- a/spec/features/projects/labels/user_removes_labels_spec.rb
+++ b/spec/features/projects/labels/user_removes_labels_spec.rb
@@ -41,7 +41,7 @@ describe "User removes labels" do
it "removes all labels" do
loop do
- li = page.first(".label-list-item")
+ li = page.first(".label-list-item", minimum: 0)
break unless li
li.find('.js-label-options-dropdown').click
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index 1de153db41c..77f0f237d0a 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -91,7 +91,7 @@ describe 'Pipeline', :js do
within '.pipeline-info' do
expect(page).to have_content("#{pipeline.statuses.count} jobs " \
- "for #{pipeline.ref} ")
+ "for #{pipeline.ref}")
expect(page).to have_link(pipeline.ref,
href: project_commits_path(pipeline.project, pipeline.ref))
end
diff --git a/spec/features/projects/settings/integration_settings_spec.rb b/spec/features/projects/settings/integration_settings_spec.rb
index 32959969f54..016ccf63f58 100644
--- a/spec/features/projects/settings/integration_settings_spec.rb
+++ b/spec/features/projects/settings/integration_settings_spec.rb
@@ -41,7 +41,7 @@ describe 'Projects > Settings > Integration settings' do
expect(page).to have_content('Issues events')
expect(page).to have_content('Confidential issues events')
expect(page).to have_content('Note events')
- expect(page).to have_content('Merge requests events')
+ expect(page).to have_content('Merge requests events')
expect(page).to have_content('Pipeline events')
expect(page).to have_content('Wiki page events')
end
diff --git a/spec/features/projects/tree/upload_file_spec.rb b/spec/features/projects/tree/upload_file_spec.rb
index dcf7d314f8e..e5dd2f40fdf 100644
--- a/spec/features/projects/tree/upload_file_spec.rb
+++ b/spec/features/projects/tree/upload_file_spec.rb
@@ -29,6 +29,6 @@ describe 'Multi-file editor upload file', :js do
attach_file('file-upload', txt_file)
expect(page).to have_selector('.multi-file-tab', text: 'doc_sample.txt')
- expect(find('.blob-editor-container .lines-content')['innerText']).to have_content(File.open(txt_file, &:readline))
+ expect(find('.blob-editor-container .lines-content')['innerText']).to have_content(File.open(txt_file, &:readline).gsub!(/\s+/, ' '))
end
end
diff --git a/spec/features/search/user_searches_for_commits_spec.rb b/spec/features/search/user_searches_for_commits_spec.rb
index 28cae444588..998f8521384 100644
--- a/spec/features/search/user_searches_for_commits_spec.rb
+++ b/spec/features/search/user_searches_for_commits_spec.rb
@@ -35,7 +35,7 @@ describe 'User searches for commits' do
fill_in('search', with: 'deadbeef')
click_button('Search')
- expect(page).to have_current_path('/search', only_path: true)
+ expect(page).to have_current_path('/search', ignore_query: true)
end
it 'finds multiple commits' do
diff --git a/spec/features/tags/master_creates_tag_spec.rb b/spec/features/tags/master_creates_tag_spec.rb
index db2970f3340..f80ddd050d7 100644
--- a/spec/features/tags/master_creates_tag_spec.rb
+++ b/spec/features/tags/master_creates_tag_spec.rb
@@ -39,7 +39,7 @@ describe 'Maintainer creates tag' do
project_tag_path(project, 'v3.0'))
expect(page).to have_content 'v3.0'
page.within 'pre.wrap' do
- expect(page).to have_content "Awesome tag message\n\n- hello\n- world"
+ expect(page).to have_content "Awesome tag message - hello - world"
end
end
diff --git a/spec/frontend/ide/components/ide_status_list_spec.js b/spec/frontend/ide/components/ide_status_list_spec.js
new file mode 100644
index 00000000000..4e0e8a9f0e3
--- /dev/null
+++ b/spec/frontend/ide/components/ide_status_list_spec.js
@@ -0,0 +1,91 @@
+import Vuex from 'vuex';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import IdeStatusList from '~/ide/components/ide_status_list';
+
+const TEST_FILE = {
+ name: 'lorem.md',
+ eol: 'LF',
+ editorRow: 3,
+ editorColumn: 23,
+ fileLanguage: 'markdown',
+};
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('ide/components/ide_status_list', () => {
+ let activeFile;
+ let store;
+ let wrapper;
+
+ const createComponent = (options = {}) => {
+ store = new Vuex.Store({
+ getters: {
+ activeFile: () => activeFile,
+ },
+ });
+
+ wrapper = shallowMount(localVue.extend(IdeStatusList), {
+ localVue,
+ sync: false,
+ store,
+ ...options,
+ });
+ };
+
+ beforeEach(() => {
+ activeFile = TEST_FILE;
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+
+ store = null;
+ wrapper = null;
+ });
+
+ const getEditorPosition = file => `${file.editorRow}:${file.editorColumn}`;
+
+ describe('with regular file', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('shows file name', () => {
+ expect(wrapper.text()).toContain(TEST_FILE.name);
+ });
+
+ it('shows file eol', () => {
+ expect(wrapper.text()).toContain(TEST_FILE.name);
+ });
+
+ it('shows file editor position', () => {
+ expect(wrapper.text()).toContain(getEditorPosition(TEST_FILE));
+ });
+
+ it('shows file language', () => {
+ expect(wrapper.text()).toContain(TEST_FILE.fileLanguage);
+ });
+ });
+
+ describe('with binary file', () => {
+ beforeEach(() => {
+ activeFile.binary = true;
+ createComponent();
+ });
+
+ it('does not show file editor position', () => {
+ expect(wrapper.text()).not.toContain(getEditorPosition(TEST_FILE));
+ });
+ });
+
+ it('adds slot as child of list', () => {
+ createComponent({
+ slots: {
+ default: ['<div class="js-test">Hello</div>', '<div class="js-test">World</div>'],
+ },
+ });
+
+ expect(wrapper.find('.ide-status-list').findAll('.js-test').length).toEqual(2);
+ });
+});
diff --git a/spec/javascripts/monitoring/charts/area_spec.js b/spec/javascripts/monitoring/charts/area_spec.js
index 56609665b88..ac7e0bb12a1 100644
--- a/spec/javascripts/monitoring/charts/area_spec.js
+++ b/spec/javascripts/monitoring/charts/area_spec.js
@@ -214,6 +214,20 @@ describe('Area component', () => {
});
});
+ describe('chartOptions', () => {
+ describe('yAxis formatter', () => {
+ let format;
+
+ beforeEach(() => {
+ format = areaChart.vm.chartOptions.yAxis.axisLabel.formatter;
+ });
+
+ it('rounds to 3 decimal places', () => {
+ expect(format(0.88888)).toBe('0.889');
+ });
+ });
+ });
+
describe('scatterSeries', () => {
it('utilizes deployment data', () => {
expect(areaChart.vm.scatterSeries.data).toEqual([
diff --git a/spec/javascripts/monitoring/dashboard_spec.js b/spec/javascripts/monitoring/dashboard_spec.js
index 1a371c3adaf..f9c3122088e 100644
--- a/spec/javascripts/monitoring/dashboard_spec.js
+++ b/spec/javascripts/monitoring/dashboard_spec.js
@@ -314,9 +314,7 @@ describe('Dashboard', () => {
});
setTimeout(() => {
- const selectedTimeWindow = component.$el.querySelector(
- '.js-time-window-dropdown [active="true"]',
- );
+ const selectedTimeWindow = component.$el.querySelector('.js-time-window-dropdown .active');
expect(selectedTimeWindow.textContent.trim()).toEqual('30 minutes');
done();
diff --git a/spec/javascripts/monitoring/mock_data.js b/spec/javascripts/monitoring/mock_data.js
index d9d8cb66749..82e42fe9ade 100644
--- a/spec/javascripts/monitoring/mock_data.js
+++ b/spec/javascripts/monitoring/mock_data.js
@@ -857,3 +857,68 @@ export const environmentData = [
updated_at: '2018-07-04T18:44:54.010Z',
},
];
+
+export const metricsDashboardResponse = {
+ dashboard: {
+ dashboard: 'Environment metrics',
+ priority: 1,
+ panel_groups: [
+ {
+ group: 'System metrics (Kubernetes)',
+ priority: 5,
+ panels: [
+ {
+ title: 'Memory Usage (Total)',
+ type: 'area-chart',
+ y_label: 'Total Memory Used',
+ weight: 4,
+ metrics: [
+ {
+ id: 'system_metrics_kubernetes_container_memory_total',
+ query_range:
+ 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) /1024/1024/1024',
+ label: 'Total',
+ unit: 'GB',
+ metric_id: 12,
+ prometheus_endpoint_path: 'http://test',
+ },
+ ],
+ },
+ {
+ title: 'Core Usage (Total)',
+ type: 'area-chart',
+ y_label: 'Total Cores',
+ weight: 3,
+ metrics: [
+ {
+ id: 'system_metrics_kubernetes_container_cores_total',
+ query_range:
+ 'avg(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}[15m])) by (job)) without (job)',
+ label: 'Total',
+ unit: 'cores',
+ metric_id: 13,
+ },
+ ],
+ },
+ {
+ title: 'Memory Usage (Pod average)',
+ type: 'area-chart',
+ y_label: 'Memory Used per Pod',
+ weight: 2,
+ metrics: [
+ {
+ id: 'system_metrics_kubernetes_container_memory_average',
+ query_range:
+ 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024',
+ label: 'Pod average',
+ unit: 'MB',
+ metric_id: 14,
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ status: 'success',
+};
diff --git a/spec/javascripts/monitoring/store/actions_spec.js b/spec/javascripts/monitoring/store/actions_spec.js
index a848cd24fe3..8c02e21eda2 100644
--- a/spec/javascripts/monitoring/store/actions_spec.js
+++ b/spec/javascripts/monitoring/store/actions_spec.js
@@ -3,8 +3,13 @@ import MockAdapter from 'axios-mock-adapter';
import store from '~/monitoring/stores';
import * as types from '~/monitoring/stores/mutation_types';
import {
+ fetchDashboard,
+ receiveMetricsDashboardSuccess,
+ receiveMetricsDashboardFailure,
fetchDeploymentsData,
fetchEnvironmentsData,
+ fetchPrometheusMetrics,
+ fetchPrometheusMetric,
requestMetricsData,
setEndpoints,
setGettingStartedEmptyState,
@@ -12,7 +17,12 @@ import {
import storeState from '~/monitoring/stores/state';
import testAction from 'spec/helpers/vuex_action_helper';
import { resetStore } from '../helpers';
-import { deploymentData, environmentData } from '../mock_data';
+import {
+ deploymentData,
+ environmentData,
+ metricsDashboardResponse,
+ metricsGroupsAPIResponse,
+} from '../mock_data';
describe('Monitoring store actions', () => {
let mock;
@@ -155,4 +165,158 @@ describe('Monitoring store actions', () => {
);
});
});
+
+ describe('fetchDashboard', () => {
+ let dispatch;
+ let state;
+ const response = metricsDashboardResponse;
+
+ beforeEach(() => {
+ dispatch = jasmine.createSpy();
+ state = storeState();
+ state.dashboardEndpoint = '/dashboard';
+ });
+
+ it('dispatches receive and success actions', done => {
+ const params = {};
+ mock.onGet(state.dashboardEndpoint).reply(200, response);
+
+ fetchDashboard({ state, dispatch }, params)
+ .then(() => {
+ expect(dispatch).toHaveBeenCalledWith('requestMetricsDashboard');
+ expect(dispatch).toHaveBeenCalledWith('receiveMetricsDashboardSuccess', {
+ response,
+ params,
+ });
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('dispatches failure action', done => {
+ const params = {};
+ mock.onGet(state.dashboardEndpoint).reply(500);
+
+ fetchDashboard({ state, dispatch }, params)
+ .then(() => {
+ expect(dispatch).toHaveBeenCalledWith(
+ 'receiveMetricsDashboardFailure',
+ new Error('Request failed with status code 500'),
+ );
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
+
+ describe('receiveMetricsDashboardSuccess', () => {
+ let commit;
+ let dispatch;
+
+ beforeEach(() => {
+ commit = jasmine.createSpy();
+ dispatch = jasmine.createSpy();
+ });
+
+ it('stores groups ', () => {
+ const params = {};
+ const response = metricsDashboardResponse;
+
+ receiveMetricsDashboardSuccess({ commit, dispatch }, { response, params });
+
+ expect(commit).toHaveBeenCalledWith(
+ types.RECEIVE_METRICS_DATA_SUCCESS,
+ metricsDashboardResponse.dashboard.panel_groups,
+ );
+
+ expect(dispatch).toHaveBeenCalledWith('fetchPrometheusMetrics', params);
+ });
+ });
+
+ describe('receiveMetricsDashboardFailure', () => {
+ let commit;
+
+ beforeEach(() => {
+ commit = jasmine.createSpy();
+ });
+
+ it('commits failure action', () => {
+ receiveMetricsDashboardFailure({ commit });
+
+ expect(commit).toHaveBeenCalledWith(types.RECEIVE_METRICS_DATA_FAILURE, undefined);
+ });
+
+ it('commits failure action with error', () => {
+ receiveMetricsDashboardFailure({ commit }, 'uh-oh');
+
+ expect(commit).toHaveBeenCalledWith(types.RECEIVE_METRICS_DATA_FAILURE, 'uh-oh');
+ });
+ });
+
+ describe('fetchPrometheusMetrics', () => {
+ let commit;
+ let dispatch;
+
+ beforeEach(() => {
+ commit = jasmine.createSpy();
+ dispatch = jasmine.createSpy();
+ });
+
+ it('commits empty state when state.groups is empty', done => {
+ const state = storeState();
+ const params = {};
+
+ fetchPrometheusMetrics({ state, commit, dispatch }, params)
+ .then(() => {
+ expect(commit).toHaveBeenCalledWith(types.SET_NO_DATA_EMPTY_STATE);
+ expect(dispatch).not.toHaveBeenCalled();
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('dispatches fetchPrometheusMetric for each panel query', done => {
+ const params = {};
+ const state = storeState();
+ state.groups = metricsDashboardResponse.dashboard.panel_groups;
+
+ const metric = state.groups[0].panels[0].metrics[0];
+
+ fetchPrometheusMetrics({ state, commit, dispatch }, params)
+ .then(() => {
+ expect(dispatch.calls.count()).toEqual(3);
+ expect(dispatch).toHaveBeenCalledWith('fetchPrometheusMetric', { metric, params });
+ done();
+ })
+ .catch(done.fail);
+
+ done();
+ });
+ });
+
+ describe('fetchPrometheusMetric', () => {
+ it('commits prometheus query result', done => {
+ const commit = jasmine.createSpy();
+ const params = {
+ start: '1557216349.469',
+ end: '1557218149.469',
+ };
+ const metric = metricsDashboardResponse.dashboard.panel_groups[0].panels[0].metrics[0];
+ const state = storeState();
+
+ const data = metricsGroupsAPIResponse.data[0].metrics[0].queries[0];
+ const response = { data };
+ mock.onGet('http://test').reply(200, response);
+
+ fetchPrometheusMetric({ state, commit }, { metric, params });
+
+ setTimeout(() => {
+ expect(commit).toHaveBeenCalledWith(types.SET_QUERY_RESULT, {
+ metricId: metric.metric_id,
+ result: data.result,
+ });
+ done();
+ });
+ });
+ });
});
diff --git a/spec/javascripts/monitoring/store/mutations_spec.js b/spec/javascripts/monitoring/store/mutations_spec.js
index 882ee1dec14..02ff5847b34 100644
--- a/spec/javascripts/monitoring/store/mutations_spec.js
+++ b/spec/javascripts/monitoring/store/mutations_spec.js
@@ -1,7 +1,7 @@
import mutations from '~/monitoring/stores/mutations';
import * as types from '~/monitoring/stores/mutation_types';
import state from '~/monitoring/stores/state';
-import { metricsGroupsAPIResponse, deploymentData } from '../mock_data';
+import { metricsGroupsAPIResponse, deploymentData, metricsDashboardResponse } from '../mock_data';
describe('Monitoring mutations', () => {
let stateCopy;
@@ -11,14 +11,16 @@ describe('Monitoring mutations', () => {
});
describe(types.RECEIVE_METRICS_DATA_SUCCESS, () => {
+ let groups;
+
beforeEach(() => {
stateCopy.groups = [];
- const groups = metricsGroupsAPIResponse.data;
-
- mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
+ groups = metricsGroupsAPIResponse.data;
});
it('normalizes values', () => {
+ mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
+
const expectedTimestamp = '2017-05-25T08:22:34.925Z';
const expectedValue = 0.0010794445585559514;
const [timestamp, value] = stateCopy.groups[0].metrics[0].queries[0].result[0].values[0];
@@ -28,22 +30,27 @@ describe('Monitoring mutations', () => {
});
it('contains two groups that contains, one of which has two queries sorted by priority', () => {
+ mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
+
expect(stateCopy.groups).toBeDefined();
expect(stateCopy.groups.length).toEqual(2);
expect(stateCopy.groups[0].metrics.length).toEqual(2);
});
it('assigns queries a metric id', () => {
+ mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
+
expect(stateCopy.groups[1].metrics[0].queries[0].metricId).toEqual('100');
});
it('removes the data if all the values from a query are not defined', () => {
+ mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
+
expect(stateCopy.groups[1].metrics[0].queries[0].result.length).toEqual(0);
});
it('assigns metric id of null if metric has no id', () => {
stateCopy.groups = [];
- const groups = metricsGroupsAPIResponse.data;
const noId = groups.map(group => ({
...group,
...{
@@ -63,6 +70,26 @@ describe('Monitoring mutations', () => {
});
});
});
+
+ describe('dashboard endpoint enabled', () => {
+ const dashboardGroups = metricsDashboardResponse.dashboard.panel_groups;
+
+ beforeEach(() => {
+ stateCopy.useDashboardEndpoint = true;
+ });
+
+ it('aliases group panels to metrics for backwards compatibility', () => {
+ mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, dashboardGroups);
+
+ expect(stateCopy.groups[0].metrics[0]).toBeDefined();
+ });
+
+ it('aliases panel metrics to queries for backwards compatibility', () => {
+ mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, dashboardGroups);
+
+ expect(stateCopy.groups[0].metrics[0].queries).toBeDefined();
+ });
+ });
});
describe(types.RECEIVE_DEPLOYMENTS_DATA_SUCCESS, () => {
@@ -82,11 +109,51 @@ describe('Monitoring mutations', () => {
metricsEndpoint: 'additional_metrics.json',
environmentsEndpoint: 'environments.json',
deploymentsEndpoint: 'deployments.json',
+ dashboardEndpoint: 'dashboard.json',
});
expect(stateCopy.metricsEndpoint).toEqual('additional_metrics.json');
expect(stateCopy.environmentsEndpoint).toEqual('environments.json');
expect(stateCopy.deploymentsEndpoint).toEqual('deployments.json');
+ expect(stateCopy.dashboardEndpoint).toEqual('dashboard.json');
+ });
+ });
+
+ describe('SET_QUERY_RESULT', () => {
+ const metricId = 12;
+ const result = [{ values: [[0, 1], [1, 1], [1, 3]] }];
+
+ beforeEach(() => {
+ stateCopy.useDashboardEndpoint = true;
+ const dashboardGroups = metricsDashboardResponse.dashboard.panel_groups;
+ mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, dashboardGroups);
+ });
+
+ it('clears empty state', () => {
+ mutations[types.SET_QUERY_RESULT](stateCopy, {
+ metricId,
+ result,
+ });
+
+ expect(stateCopy.showEmptyState).toBe(false);
+ });
+
+ it('sets metricsWithData value', () => {
+ mutations[types.SET_QUERY_RESULT](stateCopy, {
+ metricId,
+ result,
+ });
+
+ expect(stateCopy.metricsWithData).toEqual([12]);
+ });
+
+ it('does not store empty results', () => {
+ mutations[types.SET_QUERY_RESULT](stateCopy, {
+ metricId,
+ result: [],
+ });
+
+ expect(stateCopy.metricsWithData).toEqual([]);
});
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js
index 8e0415b813b..2ea8c169add 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js
@@ -1,17 +1,19 @@
import Vue from 'vue';
-import mwpsComponent from '~/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue';
+import autoMergeEnabledComponent from '~/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue';
import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
import eventHub from '~/vue_merge_request_widget/event_hub';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import { trimText } from 'spec/helpers/text_helper';
+import { MWPS_MERGE_STRATEGY } from '~/vue_merge_request_widget/constants';
-describe('MRWidgetMergeWhenPipelineSucceeds', () => {
+describe('MRWidgetAutoMergeEnabled', () => {
let vm;
const targetBranchPath = '/foo/bar';
const targetBranch = 'foo';
const sha = '1EA2EZ34';
beforeEach(() => {
- const Component = Vue.extend(mwpsComponent);
+ const Component = Vue.extend(autoMergeEnabledComponent);
spyOn(eventHub, '$emit');
vm = mountComponent(Component, {
@@ -25,6 +27,7 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
sha,
targetBranchPath,
targetBranch,
+ autoMergeStrategy: MWPS_MERGE_STRATEGY,
},
service: new MRWidgetService({}),
});
@@ -66,6 +69,32 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
expect(vm.canRemoveSourceBranch).toBeFalsy();
});
});
+
+ describe('statusTextBeforeAuthor', () => {
+ it('should return "Set by" if the MWPS is selected', () => {
+ Vue.set(vm.mr, 'autoMergeStrategy', MWPS_MERGE_STRATEGY);
+
+ expect(vm.statusTextBeforeAuthor).toBe('Set by');
+ });
+ });
+
+ describe('statusTextAfterAuthor', () => {
+ it('should return "to be merged automatically..." if MWPS is selected', () => {
+ Vue.set(vm.mr, 'autoMergeStrategy', MWPS_MERGE_STRATEGY);
+
+ expect(vm.statusTextAfterAuthor).toBe(
+ 'to be merged automatically when the pipeline succeeds',
+ );
+ });
+ });
+
+ describe('cancelButtonText', () => {
+ it('should return "Cancel automatic merge" if MWPS is selected', () => {
+ Vue.set(vm.mr, 'autoMergeStrategy', MWPS_MERGE_STRATEGY);
+
+ expect(vm.cancelButtonText).toBe('Cancel automatic merge');
+ });
+ });
});
describe('methods', () => {
@@ -96,7 +125,7 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
spyOn(vm.service, 'merge').and.returnValue(
Promise.resolve({
data: {
- status: 'merge_when_pipeline_succeeds',
+ status: MWPS_MERGE_STRATEGY,
},
}),
);
@@ -106,7 +135,7 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
expect(vm.service.merge).toHaveBeenCalledWith({
sha,
- auto_merge_strategy: 'merge_when_pipeline_succeeds',
+ auto_merge_strategy: MWPS_MERGE_STRATEGY,
should_remove_source_branch: true,
});
done();
@@ -119,6 +148,7 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
it('should have correct elements', () => {
expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
expect(vm.$el.innerText).toContain('to be merged automatically when the pipeline succeeds');
+
expect(vm.$el.innerText).toContain('The changes will be merged into');
expect(vm.$el.innerText).toContain(targetBranch);
expect(vm.$el.innerText).toContain('The source branch will not be deleted');
@@ -174,5 +204,27 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
done();
});
});
+
+ it('should render the status text as "...to merged automatically" if MWPS is selected', done => {
+ Vue.set(vm.mr, 'autoMergeStrategy', MWPS_MERGE_STRATEGY);
+
+ Vue.nextTick(() => {
+ const statusText = trimText(vm.$el.querySelector('.js-status-text-after-author').innerText);
+
+ expect(statusText).toBe('to be merged automatically when the pipeline succeeds');
+ done();
+ });
+ });
+
+ it('should render the cancel button as "Cancel automatic merge" if MWPS is selected', done => {
+ Vue.set(vm.mr, 'autoMergeStrategy', MWPS_MERGE_STRATEGY);
+
+ Vue.nextTick(() => {
+ const cancelButtonText = trimText(vm.$el.querySelector('.js-cancel-auto-merge').innerText);
+
+ expect(cancelButtonText).toBe('Cancel automatic merge');
+ done();
+ });
+ });
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
index 3ae773b6ccb..bb76616be56 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
@@ -6,6 +6,7 @@ import CommitEdit from '~/vue_merge_request_widget/components/states/commit_edit
import CommitMessageDropdown from '~/vue_merge_request_widget/components/states/commit_message_dropdown.vue';
import eventHub from '~/vue_merge_request_widget/event_hub';
import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { MWPS_MERGE_STRATEGY, ATMTWPS_MERGE_STRATEGY } from '~/vue_merge_request_widget/constants';
const commitMessage = 'This is the commit message';
const squashCommitMessage = 'This is the squash commit message';
@@ -29,6 +30,8 @@ const createTestMr = customConfig => {
shouldRemoveSourceBranch: true,
canRemoveSourceBranch: false,
targetBranch: 'master',
+ preferredAutoMergeStrategy: MWPS_MERGE_STRATEGY,
+ availableAutoMergeStrategies: [MWPS_MERGE_STRATEGY],
};
Object.assign(mr, customConfig.mr);
@@ -80,7 +83,6 @@ describe('ReadyToMerge', () => {
it('should have default data', () => {
expect(vm.mergeWhenBuildSucceeds).toBeFalsy();
expect(vm.useCommitMessageWithDescription).toBeFalsy();
- expect(vm.autoMergeStrategy).toBeUndefined();
expect(vm.showCommitMessageEditor).toBeFalsy();
expect(vm.isMakingRequest).toBeFalsy();
expect(vm.isMergingImmediately).toBeFalsy();
@@ -91,47 +93,51 @@ describe('ReadyToMerge', () => {
});
describe('computed', () => {
- describe('shouldShowAutoMergeText', () => {
- it('should return true with active pipeline', () => {
- vm.mr.isPipelineActive = true;
+ describe('isAutoMergeAvailable', () => {
+ it('should return true when at least one merge strategy is available', () => {
+ vm.mr.availableAutoMergeStrategies = [MWPS_MERGE_STRATEGY];
- expect(vm.shouldShowAutoMergeText).toBeTruthy();
+ expect(vm.isAutoMergeAvailable).toBe(true);
});
- it('should return false with inactive pipeline', () => {
- vm.mr.isPipelineActive = false;
+ it('should return false when no merge strategies are available', () => {
+ vm.mr.availableAutoMergeStrategies = [];
- expect(vm.shouldShowAutoMergeText).toBeFalsy();
+ expect(vm.isAutoMergeAvailable).toBe(false);
});
});
describe('status', () => {
it('defaults to success', () => {
- vm.mr.pipeline = true;
+ Vue.set(vm.mr, 'pipeline', true);
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
expect(vm.status).toEqual('success');
});
it('returns failed when MR has CI but also has an unknown status', () => {
- vm.mr.hasCI = true;
+ Vue.set(vm.mr, 'hasCI', true);
expect(vm.status).toEqual('failed');
});
it('returns default when MR has no pipeline', () => {
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
+
expect(vm.status).toEqual('success');
});
it('returns pending when pipeline is active', () => {
- vm.mr.pipeline = {};
- vm.mr.isPipelineActive = true;
+ Vue.set(vm.mr, 'pipeline', {});
+ Vue.set(vm.mr, 'isPipelineActive', true);
expect(vm.status).toEqual('pending');
});
it('returns failed when pipeline is failed', () => {
- vm.mr.pipeline = {};
- vm.mr.isPipelineFailed = true;
+ Vue.set(vm.mr, 'pipeline', {});
+ Vue.set(vm.mr, 'isPipelineFailed', true);
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
expect(vm.status).toEqual('failed');
});
@@ -143,18 +149,20 @@ describe('ReadyToMerge', () => {
const inActionClass = `${defaultClass} btn-info`;
it('defaults to success class', () => {
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
+
expect(vm.mergeButtonClass).toEqual(defaultClass);
});
it('returns success class for success status', () => {
- vm.mr.pipeline = true;
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
+ Vue.set(vm.mr, 'pipeline', true);
expect(vm.mergeButtonClass).toEqual(defaultClass);
});
it('returns info class for pending status', () => {
- vm.mr.pipeline = {};
- vm.mr.isPipelineActive = true;
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', [ATMTWPS_MERGE_STRATEGY]);
expect(vm.mergeButtonClass).toEqual(inActionClass);
});
@@ -198,69 +206,82 @@ describe('ReadyToMerge', () => {
});
describe('mergeButtonText', () => {
- it('should return Merge', () => {
+ it('should return "Merge" when no auto merge strategies are available', () => {
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
+
expect(vm.mergeButtonText).toEqual('Merge');
});
- it('should return Merge in progress', () => {
- vm.isMergingImmediately = true;
+ it('should return "Merge in progress"', () => {
+ Vue.set(vm, 'isMergingImmediately', true);
expect(vm.mergeButtonText).toEqual('Merge in progress');
});
- it('should return Merge when pipeline succeeds', () => {
- vm.isMergingImmediately = false;
- vm.mr.isPipelineActive = true;
+ it('should return "Merge when pipeline succeeds" when the MWPS auto merge strategy is available', () => {
+ Vue.set(vm, 'isMergingImmediately', false);
+ Vue.set(vm.mr, 'preferredAutoMergeStrategy', MWPS_MERGE_STRATEGY);
expect(vm.mergeButtonText).toEqual('Merge when pipeline succeeds');
});
});
+ describe('autoMergeText', () => {
+ it('should return Merge when pipeline succeeds', () => {
+ Vue.set(vm.mr, 'preferredAutoMergeStrategy', MWPS_MERGE_STRATEGY);
+
+ expect(vm.autoMergeText).toEqual('Merge when pipeline succeeds');
+ });
+ });
+
describe('shouldShowMergeOptionsDropdown', () => {
- it('should return false with initial data', () => {
- expect(vm.shouldShowMergeOptionsDropdown).toBeFalsy();
+ it('should return false when no auto merge strategies are available', () => {
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
+
+ expect(vm.shouldShowMergeOptionsDropdown).toBe(false);
});
- it('should return true when pipeline active', () => {
- vm.mr.isPipelineActive = true;
+ it('should return true when at least one auto merge strategy is available', () => {
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', [ATMTWPS_MERGE_STRATEGY]);
- expect(vm.shouldShowMergeOptionsDropdown).toBeTruthy();
+ expect(vm.shouldShowMergeOptionsDropdown).toBe(true);
});
it('should return false when pipeline active but only merge when pipeline succeeds set in project options', () => {
- vm.mr.isPipelineActive = true;
- vm.mr.onlyAllowMergeIfPipelineSucceeds = true;
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', [ATMTWPS_MERGE_STRATEGY]);
+ Vue.set(vm.mr, 'onlyAllowMergeIfPipelineSucceeds', true);
- expect(vm.shouldShowMergeOptionsDropdown).toBeFalsy();
+ expect(vm.shouldShowMergeOptionsDropdown).toBe(false);
});
});
describe('isMergeButtonDisabled', () => {
it('should return false with initial data', () => {
- vm.mr.isMergeAllowed = true;
+ Vue.set(vm.mr, 'isMergeAllowed', true);
- expect(vm.isMergeButtonDisabled).toBeFalsy();
+ expect(vm.isMergeButtonDisabled).toBe(false);
});
it('should return true when there is no commit message', () => {
- vm.mr.isMergeAllowed = true;
- vm.commitMessage = '';
+ Vue.set(vm.mr, 'isMergeAllowed', true);
+ Vue.set(vm, 'commitMessage', '');
- expect(vm.isMergeButtonDisabled).toBeTruthy();
+ expect(vm.isMergeButtonDisabled).toBe(true);
});
it('should return true if merge is not allowed', () => {
- vm.mr.isMergeAllowed = false;
- vm.mr.onlyAllowMergeIfPipelineSucceeds = true;
+ Vue.set(vm.mr, 'isMergeAllowed', false);
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
+ Vue.set(vm.mr, 'onlyAllowMergeIfPipelineSucceeds', true);
- expect(vm.isMergeButtonDisabled).toBeTruthy();
+ expect(vm.isMergeButtonDisabled).toBe(true);
});
it('should return true when the vm instance is making request', () => {
- vm.mr.isMergeAllowed = true;
- vm.isMakingRequest = true;
+ Vue.set(vm.mr, 'isMergeAllowed', true);
+ Vue.set(vm, 'isMakingRequest', true);
- expect(vm.isMergeButtonDisabled).toBeTruthy();
+ expect(vm.isMergeButtonDisabled).toBe(true);
});
});
});
@@ -268,31 +289,31 @@ describe('ReadyToMerge', () => {
describe('methods', () => {
describe('shouldShowMergeControls', () => {
it('should return false when an external pipeline is running and required to succeed', () => {
- vm.mr.isMergeAllowed = false;
- vm.mr.isPipelineActive = false;
+ Vue.set(vm.mr, 'isMergeAllowed', false);
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
- expect(vm.shouldShowMergeControls).toBeFalsy();
+ expect(vm.shouldShowMergeControls).toBe(false);
});
it('should return true when the build succeeded or build not required to succeed', () => {
- vm.mr.isMergeAllowed = true;
- vm.mr.isPipelineActive = false;
+ Vue.set(vm.mr, 'isMergeAllowed', true);
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
- expect(vm.shouldShowMergeControls).toBeTruthy();
+ expect(vm.shouldShowMergeControls).toBe(true);
});
it('should return true when showing the MWPS button and a pipeline is running that needs to be successful', () => {
- vm.mr.isMergeAllowed = false;
- vm.mr.isPipelineActive = true;
+ Vue.set(vm.mr, 'isMergeAllowed', false);
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', [MWPS_MERGE_STRATEGY]);
- expect(vm.shouldShowMergeControls).toBeTruthy();
+ expect(vm.shouldShowMergeControls).toBe(true);
});
it('should return true when showing the MWPS button but not required for the pipeline to succeed', () => {
- vm.mr.isMergeAllowed = true;
- vm.mr.isPipelineActive = true;
+ Vue.set(vm.mr, 'isMergeAllowed', true);
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', [MWPS_MERGE_STRATEGY]);
- expect(vm.shouldShowMergeControls).toBeTruthy();
+ expect(vm.shouldShowMergeControls).toBe(true);
});
});
@@ -325,7 +346,6 @@ describe('ReadyToMerge', () => {
vm.handleMergeButtonClick(true);
setTimeout(() => {
- expect(vm.autoMergeStrategy).toBe('merge_when_pipeline_succeeds');
expect(vm.isMakingRequest).toBeTruthy();
expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
@@ -349,14 +369,13 @@ describe('ReadyToMerge', () => {
vm.handleMergeButtonClick(false, true);
setTimeout(() => {
- expect(vm.autoMergeStrategy).toBeUndefined();
expect(vm.isMakingRequest).toBeTruthy();
expect(eventHub.$emit).toHaveBeenCalledWith('FailedToMerge', undefined);
const params = vm.service.merge.calls.argsFor(0)[0];
expect(params.should_remove_source_branch).toBeTruthy();
- expect(params.merge_when_pipeline_succeeds).toBeFalsy();
+ expect(params.auto_merge_strategy).toBeUndefined();
done();
}, 333);
});
@@ -367,14 +386,13 @@ describe('ReadyToMerge', () => {
vm.handleMergeButtonClick();
setTimeout(() => {
- expect(vm.autoMergeStrategy).toBeUndefined();
expect(vm.isMakingRequest).toBeTruthy();
expect(vm.initiateMergePolling).toHaveBeenCalled();
const params = vm.service.merge.calls.argsFor(0)[0];
expect(params.should_remove_source_branch).toBeTruthy();
- expect(params.merge_when_pipeline_succeeds).toBeFalsy();
+ expect(params.auto_merge_strategy).toBeUndefined();
done();
}, 333);
});
diff --git a/spec/javascripts/vue_mr_widget/mock_data.js b/spec/javascripts/vue_mr_widget/mock_data.js
index edbd0d54151..3c9a5cece90 100644
--- a/spec/javascripts/vue_mr_widget/mock_data.js
+++ b/spec/javascripts/vue_mr_widget/mock_data.js
@@ -25,7 +25,6 @@ export default {
},
merge_status: 'can_be_merged',
merge_user_id: null,
- merge_when_pipeline_succeeds: false,
source_branch: 'daaaa',
source_branch_link: 'daaaa',
source_project_id: 19,
@@ -210,8 +209,7 @@ export default {
source_branch_path: '/root/acets-app/branches/daaaa',
conflict_resolution_ui_path: '/root/acets-app/merge_requests/22/conflicts',
remove_wip_path: '/root/acets-app/merge_requests/22/remove_wip',
- cancel_merge_when_pipeline_succeeds_path:
- '/root/acets-app/merge_requests/22/cancel_merge_when_pipeline_succeeds',
+ cancel_auto_merge_path: '/root/acets-app/merge_requests/22/cancel_auto_merge',
create_issue_to_resolve_discussions_path:
'/root/acets-app/issues/new?merge_request_to_resolve_discussions_of=22',
merge_path: '/root/acets-app/merge_requests/22/merge',
@@ -237,6 +235,9 @@ export default {
merge_request_pipelines_docs_path: '/help/ci/merge_request_pipelines/index.md',
squash: true,
visual_review_app_available: true,
+ merge_trains_enabled: true,
+ merge_trains_count: 3,
+ merge_train_index: 1,
};
export const mockStore = {
diff --git a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
index 918717c4547..08f7a17515e 100644
--- a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
@@ -222,60 +222,6 @@ describe('mrWidgetOptions', () => {
});
});
});
-
- describe('showTargetBranchAdvancedError', () => {
- describe(`when the pipeline's target_sha property doesn't exist`, () => {
- beforeEach(done => {
- Vue.set(vm.mr, 'isOpen', true);
- Vue.set(vm.mr.pipeline, 'target_sha', undefined);
- Vue.set(vm.mr, 'targetBranchSha', 'abcd');
- vm.$nextTick(done);
- });
-
- it('should be false', () => {
- expect(vm.showTargetBranchAdvancedError).toEqual(false);
- });
- });
-
- describe(`when the pipeline's target_sha matches the target branch's sha`, () => {
- beforeEach(done => {
- Vue.set(vm.mr, 'isOpen', true);
- Vue.set(vm.mr.pipeline, 'target_sha', 'abcd');
- Vue.set(vm.mr, 'targetBranchSha', 'abcd');
- vm.$nextTick(done);
- });
-
- it('should be false', () => {
- expect(vm.showTargetBranchAdvancedError).toEqual(false);
- });
- });
-
- describe(`when the merge request is not open`, () => {
- beforeEach(done => {
- Vue.set(vm.mr, 'isOpen', false);
- Vue.set(vm.mr.pipeline, 'target_sha', 'abcd');
- Vue.set(vm.mr, 'targetBranchSha', 'bcde');
- vm.$nextTick(done);
- });
-
- it('should be false', () => {
- expect(vm.showTargetBranchAdvancedError).toEqual(false);
- });
- });
-
- describe(`when the pipeline's target_sha does not match the target branch's sha`, () => {
- beforeEach(done => {
- Vue.set(vm.mr, 'isOpen', true);
- Vue.set(vm.mr.pipeline, 'target_sha', 'abcd');
- Vue.set(vm.mr, 'targetBranchSha', 'bcde');
- vm.$nextTick(done);
- });
-
- it('should be true', () => {
- expect(vm.showTargetBranchAdvancedError).toEqual(true);
- });
- });
- });
});
describe('methods', () => {
diff --git a/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js b/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js
index e2cd0f084fd..e27a506f426 100644
--- a/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js
+++ b/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js
@@ -82,5 +82,47 @@ describe('MergeRequestStore', () => {
expect(store.isNothingToMergeState).toEqual(false);
});
});
+
+ describe('mergePipelinesEnabled', () => {
+ it('should set mergePipelinesEnabled = true when merge_pipelines_enabled is true', () => {
+ store.setData({ ...mockData, merge_pipelines_enabled: true });
+
+ expect(store.mergePipelinesEnabled).toBe(true);
+ });
+
+ it('should set mergePipelinesEnabled = false when merge_pipelines_enabled is not provided', () => {
+ store.setData({ ...mockData, merge_pipelines_enabled: undefined });
+
+ expect(store.mergePipelinesEnabled).toBe(false);
+ });
+ });
+
+ describe('mergeTrainsCount', () => {
+ it('should set mergeTrainsCount when merge_trains_count is provided', () => {
+ store.setData({ ...mockData, merge_trains_count: 3 });
+
+ expect(store.mergeTrainsCount).toBe(3);
+ });
+
+ it('should set mergeTrainsCount = 0 when merge_trains_count is not provided', () => {
+ store.setData({ ...mockData, merge_trains_count: undefined });
+
+ expect(store.mergeTrainsCount).toBe(0);
+ });
+ });
+
+ describe('mergeTrainIndex', () => {
+ it('should set mergeTrainIndex when merge_train_index is provided', () => {
+ store.setData({ ...mockData, merge_train_index: 3 });
+
+ expect(store.mergeTrainIndex).toBe(3);
+ });
+
+ it('should not set mergeTrainIndex when merge_train_index is not provided', () => {
+ store.setData({ ...mockData, merge_train_index: undefined });
+
+ expect(store.mergeTrainIndex).toBeUndefined();
+ });
+ });
});
});
diff --git a/spec/javascripts/vue_shared/components/table_pagination_spec.js b/spec/javascripts/vue_shared/components/table_pagination_spec.js
index 42cd41381dc..42abb4d83f0 100644
--- a/spec/javascripts/vue_shared/components/table_pagination_spec.js
+++ b/spec/javascripts/vue_shared/components/table_pagination_spec.js
@@ -1,5 +1,5 @@
import Vue from 'vue';
-import paginationComp from '~/vue_shared/components/table_pagination.vue';
+import paginationComp from '~/vue_shared/components/pagination/table_pagination.vue';
describe('Pagination component', () => {
let component;
diff --git a/spec/lib/gitlab/rack_timeout_observer_spec.rb b/spec/lib/gitlab/cluster/rack_timeout_observer_spec.rb
index 3dc1a8b68fb..68e5435450c 100644
--- a/spec/lib/gitlab/rack_timeout_observer_spec.rb
+++ b/spec/lib/gitlab/cluster/rack_timeout_observer_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-describe Gitlab::RackTimeoutObserver do
+describe Gitlab::Cluster::RackTimeoutObserver do
let(:counter) { Gitlab::Metrics::NullMetric.instance }
before do
@@ -25,7 +25,7 @@ describe Gitlab::RackTimeoutObserver do
subject { described_class.new }
- it 'increments timeout counter' do
+ it 'increments counter' do
expect(counter)
.to receive(:increment)
.with({ controller: 'foo', action: 'bar', route: nil, state: :timed_out })
@@ -45,7 +45,7 @@ describe Gitlab::RackTimeoutObserver do
subject { described_class.new }
- it 'increments timeout counter' do
+ it 'increments counter' do
allow(endpoint).to receive_message_chain('route.pattern.origin') { 'foobar' }
expect(counter)
.to receive(:increment)
@@ -54,5 +54,24 @@ describe Gitlab::RackTimeoutObserver do
subject.callback.call(env)
end
end
+
+ context 'when request is being processed' do
+ let(:endpoint) { double }
+ let(:env) do
+ {
+ ::Rack::Timeout::ENV_INFO_KEY => double(state: :active),
+ Grape::Env::API_ENDPOINT => endpoint
+ }
+ end
+
+ subject { described_class.new }
+
+ it 'does not increment counter' do
+ allow(endpoint).to receive_message_chain('route.pattern.origin') { 'foobar' }
+ expect(counter).not_to receive(:increment)
+
+ subject.callback.call(env)
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/graphql/loaders/batch_commit_loader_spec.rb b/spec/lib/gitlab/graphql/loaders/batch_lfs_oid_loader_spec.rb
index 0137b1029cd..46dd1777285 100644
--- a/spec/lib/gitlab/graphql/loaders/batch_commit_loader_spec.rb
+++ b/spec/lib/gitlab/graphql/loaders/batch_lfs_oid_loader_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe Gitlab::Graphql::Loaders::BatchCommitLoader do
+describe Gitlab::Graphql::Loaders::BatchLfsOidLoader do
include GraphqlHelpers
set(:project) { create(:project, :repository) }
diff --git a/spec/models/notification_recipient_spec.rb b/spec/models/notification_recipient_spec.rb
index 1b1ede6b14c..20278d81f6d 100644
--- a/spec/models/notification_recipient_spec.rb
+++ b/spec/models/notification_recipient_spec.rb
@@ -91,4 +91,237 @@ describe NotificationRecipient do
end
end
end
+
+ describe '#suitable_notification_level?' do
+ context 'when notification level is mention' do
+ before do
+ user.notification_settings_for(project).mention!
+ end
+
+ context 'when type is mention' do
+ let(:recipient) { described_class.new(user, :mention, target: target, project: project) }
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+
+ context 'when type is not mention' do
+ it 'returns false' do
+ expect(recipient.suitable_notification_level?).to eq false
+ end
+ end
+ end
+
+ context 'when notification level is participating' do
+ let(:notification_setting) { user.notification_settings_for(project) }
+
+ context 'when type is participating' do
+ let(:recipient) { described_class.new(user, :participating, target: target, project: project) }
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+
+ context 'when type is mention' do
+ let(:recipient) { described_class.new(user, :mention, target: target, project: project) }
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+
+ context 'with custom action' do
+ context "when action is failed_pipeline" do
+ let(:recipient) do
+ described_class.new(
+ user,
+ :watch,
+ custom_action: :failed_pipeline,
+ target: target,
+ project: project
+ )
+ end
+
+ before do
+ notification_setting.update!(failed_pipeline: true)
+ end
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+
+ context "when action is not failed_pipeline" do
+ let(:recipient) do
+ described_class.new(
+ user,
+ :watch,
+ custom_action: :success_pipeline,
+ target: target,
+ project: project
+ )
+ end
+
+ before do
+ notification_setting.update!(success_pipeline: true)
+ end
+
+ it 'returns false' do
+ expect(recipient.suitable_notification_level?).to eq false
+ end
+ end
+ end
+ end
+
+ context 'when notification level is custom' do
+ before do
+ user.notification_settings_for(project).custom!
+ end
+
+ context 'when type is participating' do
+ let(:notification_setting) { user.notification_settings_for(project) }
+ let(:recipient) do
+ described_class.new(
+ user,
+ :participating,
+ custom_action: :new_note,
+ target: target,
+ project: project
+ )
+ end
+
+ context 'with custom event enabled' do
+ before do
+ notification_setting.update!(new_note: true)
+ end
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+
+ context 'without custom event enabled' do
+ before do
+ notification_setting.update!(new_note: false)
+ end
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+ end
+
+ context 'when type is mention' do
+ let(:notification_setting) { user.notification_settings_for(project) }
+ let(:recipient) do
+ described_class.new(
+ user,
+ :mention,
+ custom_action: :new_issue,
+ target: target,
+ project: project
+ )
+ end
+
+ context 'with custom event enabled' do
+ before do
+ notification_setting.update!(new_issue: true)
+ end
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+
+ context 'without custom event enabled' do
+ before do
+ notification_setting.update!(new_issue: false)
+ end
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+ end
+
+ context 'when type is watch' do
+ let(:notification_setting) { user.notification_settings_for(project) }
+ let(:recipient) do
+ described_class.new(
+ user,
+ :watch,
+ custom_action: :failed_pipeline,
+ target: target,
+ project: project
+ )
+ end
+
+ context 'with custom event enabled' do
+ before do
+ notification_setting.update!(failed_pipeline: true)
+ end
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+
+ context 'without custom event enabled' do
+ before do
+ notification_setting.update!(failed_pipeline: false)
+ end
+
+ it 'returns false' do
+ expect(recipient.suitable_notification_level?).to eq false
+ end
+ end
+ end
+ end
+
+ context 'when notification level is watch' do
+ before do
+ user.notification_settings_for(project).watch!
+ end
+
+ context 'when type is watch' do
+ context 'without excluded watcher events' do
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+
+ context 'with excluded watcher events' do
+ let(:recipient) do
+ described_class.new(user, :watch, custom_action: :issue_due, target: target, project: project)
+ end
+
+ it 'returns false' do
+ expect(recipient.suitable_notification_level?).to eq false
+ end
+ end
+ end
+
+ context 'when type is not watch' do
+ context 'without excluded watcher events' do
+ let(:recipient) { described_class.new(user, :participating, target: target, project: project) }
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+
+ context 'with excluded watcher events' do
+ let(:recipient) do
+ described_class.new(user, :participating, custom_action: :issue_due, target: target, project: project)
+ end
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/presenters/ci/build_runner_presenter_spec.rb b/spec/presenters/ci/build_runner_presenter_spec.rb
index 620f34bac79..a4234d14255 100644
--- a/spec/presenters/ci/build_runner_presenter_spec.rb
+++ b/spec/presenters/ci/build_runner_presenter_spec.rb
@@ -134,7 +134,7 @@ describe Ci::BuildRunnerPresenter do
end
it 'defaults to git depth setting for the project' do
- expect(git_depth).to eq(build.project.default_git_depth)
+ expect(git_depth).to eq(build.project.ci_default_git_depth)
end
context 'when feature flag :ci_project_git_depth is disabled' do
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 799e84e83c1..5f7d2fa6d9c 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -1125,6 +1125,7 @@ describe API::Projects do
expect(json_response['shared_with_groups'][0]['expires_at']).to be_nil
expect(json_response['only_allow_merge_if_pipeline_succeeds']).to eq(project.only_allow_merge_if_pipeline_succeeds)
expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to eq(project.only_allow_merge_if_all_discussions_are_resolved)
+ expect(json_response['ci_default_git_depth']).to eq(project.ci_default_git_depth)
expect(json_response['merge_method']).to eq(project.merge_method.to_s)
expect(json_response['readme_url']).to eq(project.readme_url)
end
@@ -1963,6 +1964,7 @@ describe API::Projects do
snippets_enabled: true,
merge_requests_enabled: true,
merge_method: 'ff',
+ ci_default_git_depth: 20,
description: 'new description' }
put api("/projects/#{project3.id}", user4), params: project_param
diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb
index 038c958b5cc..d9ef5edb848 100644
--- a/spec/requests/api/runner_spec.rb
+++ b/spec/requests/api/runner_spec.rb
@@ -445,7 +445,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
'before_sha' => job.before_sha,
'ref_type' => 'branch',
'refspecs' => ["+refs/heads/#{job.ref}:refs/remotes/origin/#{job.ref}"],
- 'depth' => project.default_git_depth }
+ 'depth' => project.ci_default_git_depth }
end
let(:expected_steps) do
@@ -533,7 +533,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
context 'when GIT_DEPTH is not specified and there is no default git depth for the project' do
before do
- project.update!(default_git_depth: nil)
+ project.update!(ci_default_git_depth: nil)
end
it 'specifies refspecs' do
@@ -593,7 +593,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
context 'when GIT_DEPTH is not specified and there is no default git depth for the project' do
before do
- project.update!(default_git_depth: nil)
+ project.update!(ci_default_git_depth: nil)
end
it 'specifies refspecs' do
diff --git a/spec/services/auto_merge/base_service_spec.rb b/spec/services/auto_merge/base_service_spec.rb
index 35d60d6abbb..cd08e0b6f32 100644
--- a/spec/services/auto_merge/base_service_spec.rb
+++ b/spec/services/auto_merge/base_service_spec.rb
@@ -92,6 +92,30 @@ describe AutoMerge::BaseService do
end
end
+ describe '#update' do
+ subject { service.update(merge_request) }
+
+ let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
+
+ context 'when merge params are specified' do
+ let(:params) do
+ {
+ 'commit_message' => "Merge branch 'patch-12' into 'master'",
+ 'sha' => "200fcc9c260f7219eaf0daba87d818f0922c5b18",
+ 'should_remove_source_branch' => false,
+ 'squash' => false,
+ 'squash_commit_message' => "Update README.md"
+ }
+ end
+
+ it 'updates merge params' do
+ expect { subject }.to change {
+ merge_request.reload.merge_params.slice(*params.keys)
+ }.from({}).to(params)
+ end
+ end
+ end
+
describe '#cancel' do
subject { service.cancel(merge_request) }
diff --git a/spec/services/auto_merge_service_spec.rb b/spec/services/auto_merge_service_spec.rb
index d0eefed3150..93a22e60498 100644
--- a/spec/services/auto_merge_service_spec.rb
+++ b/spec/services/auto_merge_service_spec.rb
@@ -10,8 +10,8 @@ describe AutoMergeService do
describe '.all_strategies' do
subject { described_class.all_strategies }
- it 'returns all strategies' do
- is_expected.to eq(AutoMergeService::STRATEGIES)
+ it 'includes merge when pipeline succeeds' do
+ is_expected.to include(AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
end
end
@@ -92,6 +92,30 @@ describe AutoMergeService do
end
end
+ describe '#update' do
+ subject { service.update(merge_request) }
+
+ context 'when auto merge is enabled' do
+ let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
+
+ it 'delegates to a relevant service instance' do
+ expect_next_instance_of(AutoMerge::MergeWhenPipelineSucceedsService) do |service|
+ expect(service).to receive(:update).with(merge_request)
+ end
+
+ subject
+ end
+ end
+
+ context 'when auto merge is not enabled' do
+ let(:merge_request) { create(:merge_request) }
+
+ it 'returns failed' do
+ is_expected.to eq(:failed)
+ end
+ end
+ end
+
describe '#process' do
subject { service.process(merge_request) }
diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb
index 3211a6e1310..6afc91d5e95 100644
--- a/spec/services/projects/fork_service_spec.rb
+++ b/spec/services/projects/fork_service_spec.rb
@@ -150,21 +150,21 @@ describe Projects::ForkService do
context "when origin has git depth specified" do
before do
- @from_project.update(default_git_depth: 42)
+ @from_project.update(ci_default_git_depth: 42)
end
it "inherits default_git_depth from the origin project" do
- expect(to_project.default_git_depth).to eq(42)
+ expect(to_project.ci_default_git_depth).to eq(42)
end
end
context "when origin does not define git depth" do
before do
- @from_project.update!(default_git_depth: nil)
+ @from_project.update!(ci_default_git_depth: nil)
end
it "the fork has git depth set to 0" do
- expect(to_project.default_git_depth).to eq(0)
+ expect(to_project.ci_default_git_depth).to eq(0)
end
end
end
diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb
index 14ce3c32e77..56ac208a025 100644
--- a/spec/support/capybara.rb
+++ b/spec/support/capybara.rb
@@ -53,9 +53,11 @@ Capybara.register_driver :chrome do |app|
)
end
+Capybara.server = :webrick
Capybara.javascript_driver = :chrome
Capybara.default_max_wait_time = timeout
Capybara.ignore_hidden_elements = true
+Capybara.default_normalize_ws = true
# Keep only the screenshots generated from the last failing test suite
Capybara::Screenshot.prune_strategy = :keep_last_run
diff --git a/spec/support/features/discussion_comments_shared_example.rb b/spec/support/features/discussion_comments_shared_example.rb
index 542f533d590..0f8af2c5d6d 100644
--- a/spec/support/features/discussion_comments_shared_example.rb
+++ b/spec/support/features/discussion_comments_shared_example.rb
@@ -84,7 +84,7 @@ shared_examples 'discussion comments' do |resource_name|
#
# if dropdown menu is not toggled (and also not present),
# it's "issue-type" dropdown
- if first(menu_selector).nil?
+ if first(menu_selector, minimum: 0).nil?
expect(find(dropdown_selector)).to have_content 'Comment'
find(toggle_selector).click
diff --git a/spec/support/shared_examples/quick_actions/issuable/shrug_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/shrug_quick_action_shared_examples.rb
index 0a526808585..b592cf16f67 100644
--- a/spec/support/shared_examples/quick_actions/issuable/shrug_quick_action_shared_examples.rb
+++ b/spec/support/shared_examples/quick_actions/issuable/shrug_quick_action_shared_examples.rb
@@ -27,7 +27,7 @@ shared_examples 'shrug quick action' do |issuable_type|
expect(issuable.description).to eq "bug description\noops ¯\\_(ツ)_/¯"
expect(page).to have_content 'bug 345'
- expect(page).to have_content "bug description\noops ¯\\_(ツ)_/¯"
+ expect(page).to have_content "bug description oops ¯\\_(ツ)_/¯"
end
end
diff --git a/spec/support/shared_examples/quick_actions/issuable/tableflip_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/tableflip_quick_action_shared_examples.rb
index ef831e39872..c174127c4ff 100644
--- a/spec/support/shared_examples/quick_actions/issuable/tableflip_quick_action_shared_examples.rb
+++ b/spec/support/shared_examples/quick_actions/issuable/tableflip_quick_action_shared_examples.rb
@@ -27,7 +27,7 @@ shared_examples 'tableflip quick action' do |issuable_type|
expect(issuable.description).to eq "bug description\noops (╯°□°)╯︵ ┻━┻"
expect(page).to have_content 'bug 345'
- expect(page).to have_content "bug description\noops (╯°□°)╯︵ ┻━┻"
+ expect(page).to have_content "bug description oops (╯°□°)╯︵ ┻━┻"
end
end
diff --git a/spec/views/notify/pipeline_failed_email.html.haml_spec.rb b/spec/views/notify/pipeline_failed_email.html.haml_spec.rb
index d9d73f789c5..d04affc7df1 100644
--- a/spec/views/notify/pipeline_failed_email.html.haml_spec.rb
+++ b/spec/views/notify/pipeline_failed_email.html.haml_spec.rb
@@ -28,7 +28,7 @@ describe 'notify/pipeline_failed_email.html.haml' do
expect(rendered).to have_content "Your pipeline has failed"
expect(rendered).to have_content pipeline.project.name
- expect(rendered).to have_content pipeline.git_commit_message.truncate(50)
+ expect(rendered).to have_content pipeline.git_commit_message.truncate(50).gsub!(/\s+/, ' ')
expect(rendered).to have_content pipeline.commit.author_name
expect(rendered).to have_content "##{pipeline.id}"
expect(rendered).to have_content pipeline.user.name
@@ -45,7 +45,7 @@ describe 'notify/pipeline_failed_email.html.haml' do
expect(rendered).to have_content "Your pipeline has failed"
expect(rendered).to have_content pipeline.project.name
- expect(rendered).to have_content pipeline.git_commit_message.truncate(50)
+ expect(rendered).to have_content pipeline.git_commit_message.truncate(50).gsub!(/\s+/, ' ')
expect(rendered).to have_content pipeline.commit.author_name
expect(rendered).to have_content "##{pipeline.id}"
expect(rendered).to have_content "by API"
diff --git a/spec/views/notify/pipeline_failed_email.text.erb_spec.rb b/spec/views/notify/pipeline_failed_email.text.erb_spec.rb
index a7d3dc09fd4..079fb865d7b 100644
--- a/spec/views/notify/pipeline_failed_email.text.erb_spec.rb
+++ b/spec/views/notify/pipeline_failed_email.text.erb_spec.rb
@@ -30,7 +30,7 @@ describe 'notify/pipeline_failed_email.text.erb' do
expect(rendered).to have_content('Your pipeline has failed')
expect(rendered).to have_content(pipeline.project.name)
- expect(rendered).to have_content(pipeline.git_commit_message.truncate(50))
+ expect(rendered).to have_content(pipeline.git_commit_message.truncate(50).gsub!(/\s+/, ' '))
expect(rendered).to have_content(pipeline.commit.author_name)
expect(rendered).to have_content("##{pipeline.id}")
expect(rendered).to have_content(pipeline.user.name)
diff --git a/spec/views/notify/pipeline_success_email.html.haml_spec.rb b/spec/views/notify/pipeline_success_email.html.haml_spec.rb
index a793b37e412..8ee7f954d70 100644
--- a/spec/views/notify/pipeline_success_email.html.haml_spec.rb
+++ b/spec/views/notify/pipeline_success_email.html.haml_spec.rb
@@ -28,7 +28,7 @@ describe 'notify/pipeline_success_email.html.haml' do
expect(rendered).to have_content "Your pipeline has passed"
expect(rendered).to have_content pipeline.project.name
- expect(rendered).to have_content pipeline.git_commit_message.truncate(50)
+ expect(rendered).to have_content pipeline.git_commit_message.truncate(50).gsub!(/\s+/, ' ')
expect(rendered).to have_content pipeline.commit.author_name
expect(rendered).to have_content "##{pipeline.id}"
expect(rendered).to have_content pipeline.user.name
@@ -45,7 +45,7 @@ describe 'notify/pipeline_success_email.html.haml' do
expect(rendered).to have_content "Your pipeline has passed"
expect(rendered).to have_content pipeline.project.name
- expect(rendered).to have_content pipeline.git_commit_message.truncate(50)
+ expect(rendered).to have_content pipeline.git_commit_message.truncate(50).gsub!(/\s+/, ' ')
expect(rendered).to have_content pipeline.commit.author_name
expect(rendered).to have_content "##{pipeline.id}"
expect(rendered).to have_content "by API"
diff --git a/spec/views/profiles/show.html.haml_spec.rb b/spec/views/profiles/show.html.haml_spec.rb
index e89a8cb9626..9e7ac0b84fa 100644
--- a/spec/views/profiles/show.html.haml_spec.rb
+++ b/spec/views/profiles/show.html.haml_spec.rb
@@ -12,8 +12,8 @@ describe 'profiles/show' do
it 'displays the correct elements' do
render
- expect(rendered).to have_field('user_name', user.name)
- expect(rendered).to have_field('user_id', user.id)
+ expect(rendered).to have_field('user_name', with: user.name)
+ expect(rendered).to have_field('user_id', with: user.id)
end
end
end