summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml1
-rw-r--r--CHANGELOG.md130
-rw-r--r--GITLAB_WORKHORSE_VERSION2
-rw-r--r--VERSION2
-rw-r--r--app/assets/javascripts/droplab/droplab.js61
-rw-r--r--app/assets/javascripts/extensions/custom_event.js.es612
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_hint.js.es62
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_non_user.js.es62
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_user.js.es62
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_utils.js.es653
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_dropdown.js.es65
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js.es652
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_manager.js.es637
-rw-r--r--app/assets/javascripts/group_avatar.js4
-rw-r--r--app/assets/javascripts/merge_request_widget.js.es64
-rw-r--r--app/assets/javascripts/merge_request_widget/ci_bundle.js.es645
-rw-r--r--app/assets/javascripts/vue_pipelines_index/stage.js.es631
-rw-r--r--app/assets/stylesheets/pages/issuable.scss4
-rw-r--r--app/controllers/projects/hooks_controller.rb14
-rw-r--r--app/controllers/projects/issues_controller.rb12
-rw-r--r--app/controllers/projects/services_controller.rb4
-rw-r--r--app/controllers/projects/settings/integrations_controller.rb18
-rw-r--r--app/helpers/gitlab_routing_helper.rb4
-rw-r--r--app/models/ci/runner.rb8
-rw-r--r--app/models/key.rb7
-rw-r--r--app/serializers/pipeline_entity.rb10
-rw-r--r--app/services/ci/update_build_queue_service.rb8
-rw-r--r--app/views/layouts/nav/_project_settings.html.haml10
-rw-r--r--app/views/projects/hooks/_index.html.haml (renamed from app/views/projects/hooks/index.html.haml)0
-rw-r--r--app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml3
-rw-r--r--app/views/projects/services/_index.html.haml (renamed from app/views/projects/services/index.html.haml)2
-rw-r--r--app/views/projects/settings/integrations/_project_hook.html.haml (renamed from app/views/projects/hooks/_project_hook.html.haml)0
-rw-r--r--app/views/projects/settings/integrations/show.html.haml3
-rw-r--r--app/views/shared/_choose_group_avatar_button.html.haml2
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml16
-rw-r--r--app/views/shared/web_hooks/_form.html.haml3
-rw-r--r--changelogs/unreleased/18786-go-to-a-project-order.yml4
-rw-r--r--changelogs/unreleased/19086-double-newline.yml4
-rw-r--r--changelogs/unreleased/19966-api-call-to-move-project-to-different-group-fails-when-using-group-and-project-names-instead-of-id.yml4
-rw-r--r--changelogs/unreleased/19988-prevent-empty-pagination-when-list-not-empty.yml4
-rw-r--r--changelogs/unreleased/21135-resolve-these-conflicts-link-is-too-subtle.yml4
-rw-r--r--changelogs/unreleased/21698-redis-runner-last-build.yml4
-rw-r--r--changelogs/unreleased/22111-remove-lock-icon-on-protected-tag.yml4
-rw-r--r--changelogs/unreleased/24032-changed-visibility-level-to-public-but-project-is-not-public.yml4
-rw-r--r--changelogs/unreleased/24139-production-wildcard-for-cycle-analytics.yml4
-rw-r--r--changelogs/unreleased/24185-legacy-ci-status-reactive-cache.yml4
-rw-r--r--changelogs/unreleased/24820-buttons-in-the-branches-page-are-stacking-on-top-of-each-other-depending-on-the-selected-filter.yml4
-rw-r--r--changelogs/unreleased/24876-page-jumps-to-wrong-position-when-clicking-a-comment-anchor.yml4
-rw-r--r--changelogs/unreleased/24915_merge_slash_command.yml4
-rw-r--r--changelogs/unreleased/25277-milestone-counter-number-with-delimiter.yml4
-rw-r--r--changelogs/unreleased/25371-environments-date-created-column-is-not-labeled.yml4
-rw-r--r--changelogs/unreleased/25430-make-colors-in-runner-status-more-colorblind-friendly.yml4
-rw-r--r--changelogs/unreleased/25507-handle-errors-environment-list.yml4
-rw-r--r--changelogs/unreleased/25580-trucate-dropdown-for-long-branch.yml4
-rw-r--r--changelogs/unreleased/25678-remove-user-build.yml4
-rw-r--r--changelogs/unreleased/25701-standardize-text-colors.yml4
-rw-r--r--changelogs/unreleased/25705-your-commands-have-been-executed-is-overkill.yml3
-rw-r--r--changelogs/unreleased/25725-remove-window-object.yml4
-rw-r--r--changelogs/unreleased/25776-alerts-should-be-responsive.yml4
-rw-r--r--changelogs/unreleased/25829-update-username-button-remains-disabled-upon-failure.yml4
-rw-r--r--changelogs/unreleased/25898-ci-icon-color-mr.yml4
-rw-r--r--changelogs/unreleased/25941-odd-overflow-behavior-for-long-issue-headers.yml4
-rw-r--r--changelogs/unreleased/25946-manual-pipeline-dropdown-casing.yml4
-rw-r--r--changelogs/unreleased/25985-combine-members-and-groups-settings-pages.yml5
-rw-r--r--changelogs/unreleased/25996-Move-award-emoji-out-of-the-discussion-tab-for-MR.yml4
-rw-r--r--changelogs/unreleased/26014-fix-update-doc.yml4
-rw-r--r--changelogs/unreleased/26051-fix-missing-endpoint-route-method.yml4
-rw-r--r--changelogs/unreleased/26109-preserve-scroll-position-on-autoreload.yml4
-rw-r--r--changelogs/unreleased/26129-add-link-to-branches-page.yml4
-rw-r--r--changelogs/unreleased/26134-ctrl-enter-does-not-submit-a-new-merge-request.yml4
-rw-r--r--changelogs/unreleased/26155-merge-request-tabs-don-t-render-when-no-commits-available.yml4
-rw-r--r--changelogs/unreleased/26192-fixes-too-short-input.yml4
-rw-r--r--changelogs/unreleased/26207-add-hover-animations.yml4
-rw-r--r--changelogs/unreleased/26226-generate-all-haml-fixtures-within-teaspoon-fixtures-task.yml4
-rw-r--r--changelogs/unreleased/26238-buttons-not-accessible.yml4
-rw-r--r--changelogs/unreleased/26261-post-api-v3-projects-idorproject-commits-commits-does-not-work-with-project-path.yml4
-rw-r--r--changelogs/unreleased/26352-user-dropdown-settings.yml4
-rw-r--r--changelogs/unreleased/26435-show-project-avatars-on-mobile.yml4
-rw-r--r--changelogs/unreleased/26445-make-icon-buttons-accessible-via-keyboard.yml4
-rw-r--r--changelogs/unreleased/26446-access-download-artifacts-via-keyboard.yml5
-rw-r--r--changelogs/unreleased/26472-math-margin.yml4
-rw-r--r--changelogs/unreleased/26504-mr-discussion-btn.yml4
-rw-r--r--changelogs/unreleased/26587-metrics-middleware-endpoint-is-nil.yml4
-rw-r--r--changelogs/unreleased/26601-dropdown-makes-request-close.yml4
-rw-r--r--changelogs/unreleased/26615-pipeline-status-cell.yml4
-rw-r--r--changelogs/unreleased/26616-fix-search-group-project-filters.yml4
-rw-r--r--changelogs/unreleased/26667-pipeline-width-for-huge-pipeline.yml4
-rw-r--r--changelogs/unreleased/26773-fix-project-statistics-repository-size.yml4
-rw-r--r--changelogs/unreleased/26785-fix-droplab-in-ie-11-v1.yml4
-rw-r--r--changelogs/unreleased/7898-fixes-issue-boards-list-colored-top-border-visual-glitch.yml4
-rw-r--r--changelogs/unreleased/8623-correct-robots-txt.yml4
-rw-r--r--changelogs/unreleased/add-changelog-search-bar-first-iteration.yml4
-rw-r--r--changelogs/unreleased/add_email_password_confirmation.yml4
-rw-r--r--changelogs/unreleased/additional-award-emoji-repositioning-fixes.yml4
-rw-r--r--changelogs/unreleased/allow_plus_sign_for_snippets.yml4
-rw-r--r--changelogs/unreleased/asciidoctor-plantuml.yml4
-rw-r--r--changelogs/unreleased/badge-color-on-white-bg.yml4
-rw-r--r--changelogs/unreleased/bug-project-feature-compatibility.yml5
-rw-r--r--changelogs/unreleased/clipboard-button-text.yml3
-rw-r--r--changelogs/unreleased/didemacet-ci-lint-page.yml4
-rw-r--r--changelogs/unreleased/dot-in-project-queries.yml4
-rw-r--r--changelogs/unreleased/dz-nested-group-misc.yml4
-rw-r--r--changelogs/unreleased/dz-rename-invalid-users.yml4
-rw-r--r--changelogs/unreleased/env-var-in-redis-config.yml4
-rw-r--r--changelogs/unreleased/feature-1376-allow-write-access-deploy-keys.yml4
-rw-r--r--changelogs/unreleased/feature-admin-merge-groups-and-projects.yml4
-rw-r--r--changelogs/unreleased/feature-gitaly-feature-flag.yml4
-rw-r--r--changelogs/unreleased/feature-log-ldap-to-application-log.yml4
-rw-r--r--changelogs/unreleased/feature-more-storage-statistics.yml4
-rw-r--r--changelogs/unreleased/filename-to-file-path.yml3
-rw-r--r--changelogs/unreleased/fill-authorized-projects.yml4
-rw-r--r--changelogs/unreleased/fix-api-deprecation.yml4
-rw-r--r--changelogs/unreleased/fix-blame-500.yml4
-rw-r--r--changelogs/unreleased/fix-boards-search-typo.yml4
-rw-r--r--changelogs/unreleased/fix-broken-url-on-group-avatar.yml4
-rw-r--r--changelogs/unreleased/fix-build-sort-order.yml4
-rw-r--r--changelogs/unreleased/fix-copy-issues-empty-state.yml4
-rw-r--r--changelogs/unreleased/fix-external-status-badge-links.yml4
-rw-r--r--changelogs/unreleased/fix-keep-artifacts-button-visibility.yml4
-rw-r--r--changelogs/unreleased/fix-light-hr-in-descriptions.yml4
-rw-r--r--changelogs/unreleased/fix-more-orphans-remove-undeleted-groups.yml4
-rw-r--r--changelogs/unreleased/fix-no-milestone-option-for-projects-endpoint-23194.yml4
-rw-r--r--changelogs/unreleased/fix-project-delete-tooltip.yml4
-rw-r--r--changelogs/unreleased/fix-serialized-commit-path.yml4
-rw-r--r--changelogs/unreleased/fix-timezone-due-date-picker.yml4
-rw-r--r--changelogs/unreleased/fix-user-api-confirm-param.yml4
-rw-r--r--changelogs/unreleased/get_last_used_date_of_ssh_key.yml4
-rw-r--r--changelogs/unreleased/i--25814-500-error.yml4
-rw-r--r--changelogs/unreleased/input-button-hover.yml4
-rw-r--r--changelogs/unreleased/issue-boards-animate.yml4
-rw-r--r--changelogs/unreleased/issue_22664.yml4
-rw-r--r--changelogs/unreleased/issue_25017.yml4
-rw-r--r--changelogs/unreleased/issue_25578.yml4
-rw-r--r--changelogs/unreleased/issue_25682.yml4
-rw-r--r--changelogs/unreleased/issues-8081.yml4
-rw-r--r--changelogs/unreleased/ldap_maint_task.yml4
-rw-r--r--changelogs/unreleased/login-page-font-size.yml4
-rw-r--r--changelogs/unreleased/markdown-area-height-fix.yml4
-rw-r--r--changelogs/unreleased/merge-dropdown-this-context.yml4
-rw-r--r--changelogs/unreleased/mr-tabs-alignment-sidebar-open.yml4
-rw-r--r--changelogs/unreleased/nuke-ugly-spaces-in-changelog-generator.yml4
-rw-r--r--changelogs/unreleased/pc-add-gitaly-to-architecture.yml4
-rw-r--r--changelogs/unreleased/pipelines-graph-html-css.yml4
-rw-r--r--changelogs/unreleased/pmq20-gitlab-ce-psvr-head-cache.yml4
-rw-r--r--changelogs/unreleased/re-style-issue-new-branch.yml3
-rw-r--r--changelogs/unreleased/recaptcha_500.yml4
-rw-r--r--changelogs/unreleased/reduce-queries-milestone-index.yml4
-rw-r--r--changelogs/unreleased/refresh-authorizations-tighter-lease.yml4
-rw-r--r--changelogs/unreleased/remove-project-authorizations-id-column.yml4
-rw-r--r--changelogs/unreleased/remove-successful-pipeline-emails-for-now.yml4
-rw-r--r--changelogs/unreleased/restore-backup-when-env-variable-is-passed.yml4
-rw-r--r--changelogs/unreleased/sandish-gitlab-ce-update_ret_val.yml4
-rw-r--r--changelogs/unreleased/single-edit-comment-widget-2.yml5
-rw-r--r--changelogs/unreleased/speed-up-dashboard-milestone-index.yml5
-rw-r--r--changelogs/unreleased/support-google-cloud-storage-backups.yml4
-rw-r--r--changelogs/unreleased/time-tracking-api.yml4
-rw-r--r--changelogs/unreleased/update-gitlab-markup-gem.yml4
-rw-r--r--changelogs/unreleased/validate-title-length.yml4
-rw-r--r--changelogs/unreleased/view-ce-vs-ee.yml4
-rw-r--r--changelogs/unreleased/zj-unadressable-url-variables.yml4
-rw-r--r--config/routes/project.rb2
-rw-r--r--db/migrate/20170121123724_add_index_to_ci_builds_for_status_runner_id_and_type.rb17
-rw-r--r--db/migrate/20170121130655_add_index_to_ci_runners_for_is_shared.rb17
-rw-r--r--db/schema.rb4
-rw-r--r--doc/README.md3
-rw-r--r--doc/administration/monitoring/performance/introduction.md5
-rw-r--r--doc/administration/monitoring/performance/prometheus.md102
-rw-r--r--doc/api/README.md8
-rw-r--r--doc/integration/oauth_provider.md8
-rw-r--r--features/project/active_tab.feature6
-rw-r--r--features/steps/project/active_tab.rb8
-rw-r--r--features/steps/project/hooks.rb6
-rw-r--r--features/steps/project/services.rb2
-rw-r--r--features/steps/shared/paths.rb2
-rw-r--r--lib/gitlab/import_export/members_mapper.rb8
-rw-r--r--lib/gitlab/import_export/relation_factory.rb12
-rw-r--r--spec/controllers/projects/settings/integrations_controller_spec.rb20
-rw-r--r--spec/features/issues/filtered_search/dropdown_assignee_spec.rb16
-rw-r--r--spec/features/issues/filtered_search/filter_issues_spec.rb49
-rw-r--r--spec/features/merge_requests/merge_immediately_with_pipeline_spec.rb41
-rw-r--r--spec/features/merge_requests/merge_when_pipeline_succeeds_spec.rb60
-rw-r--r--spec/features/security/project/internal_access_spec.rb4
-rw-r--r--spec/features/security/project/private_access_spec.rb4
-rw-r--r--spec/features/security/project/public_access_spec.rb4
-rw-r--r--spec/finders/move_to_project_finder_spec.rb20
-rw-r--r--spec/javascripts/filtered_search/dropdown_utils_spec.js.es641
-rw-r--r--spec/lib/gitlab/import_export/members_mapper_spec.rb34
-rw-r--r--spec/lib/gitlab/import_export/relation_factory_spec.rb58
-rw-r--r--spec/models/key_spec.rb27
-rw-r--r--spec/models/merge_request_spec.rb44
-rw-r--r--spec/models/project_spec.rb108
-rw-r--r--spec/models/user_spec.rb84
-rw-r--r--spec/requests/projects/cycle_analytics_events_spec.rb35
-rw-r--r--spec/serializers/pipeline_entity_spec.rb12
-rw-r--r--spec/services/ci/update_build_queue_service_spec.rb47
-rw-r--r--vendor/gitlab-ci-yml/autodeploy/Kubernetes.gitlab-ci.yml76
196 files changed, 1233 insertions, 831 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 68690ff33da..d30deef0096 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -35,7 +35,6 @@ stages:
.dedicated-runner: &dedicated-runner
tags:
- gitlab-org
- - 2gb
.knapsack-state: &knapsack-state
services: []
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cabfef84b24..aecacbee2f5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,136 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 8.16.0 (2017-02-22)
+
+- Add LDAP Rake task to rename a provider. !2181
+- Validate label's title length. !5767 (Tomáš Kukrál)
+- Allow to add deploy keys with write-access. !5807 (Ali Ibrahim)
+- Allow to use + symbol in filenames. !6644 (blackst0ne)
+- Search bar redesign first iteration. !7345
+- Fix date inconsistency on due date picker. !7422 (Giuliano Varriale)
+- Add email confirmation field to registration form. !7432
+- Updated project visibility settings UX. !7645
+- Go to a project order. !7737 (Jacopo Beschi @jacopo-beschi)
+- Support slash comand `/merge` for merging merge requests. !7746 (Jarka Kadlecova)
+- Add more storage statistics. !7754 (Markus Koller)
+- Add support for PlantUML diagrams in AsciiDoc documents. !7810 (Horacio Sanson)
+- Remove extra orphaned rows when removing stray namespaces. !7841
+- Added lighter count badge background-color for on white backgrounds. !7873
+- Fixes issue boards list colored top border visual glitch. !7898 (Pier Paolo Ramon)
+- change 'gray' color theme name to 'black' to match the actual color. !7908 (BM5k)
+- Remove trailing whitespace when generating changelog entry. !7948
+- Remove checking branches state in issue new branch button. !8023
+- Log LDAP blocking/unblocking events to application log. !8042 (Markus Koller)
+- ensure permalinks scroll to correct position on multiple clicks. !8046
+- Allow to use ENV variables in redis config. !8073 (Semyon Pupkov)
+- fix button layout issue on branches page. !8074
+- Reduce DB-load for build-queues by storing last_update in Redis. !8084
+- Record and show last used date of SSH Keys. !8113 (Vincent Wong)
+- Resolves overflow in compare branch and tags dropdown. !8118
+- Replace wording for slash command confirmation message. !8123
+- remove build_user. !8162 (Arsenev Vladislav)
+- Prevent empty pagination when list is not empty. !8172
+- Make successful pipeline emails off for watchers. !8176
+- Improve copy in Issue Tracker empty state. !8202
+- Adds CSS class to status icon on MR widget to prevent non-colored icon. !8219
+- Improve visibility of "Resolve conflicts" and "Merge locally" actions. !8229
+- Add Gitaly to the architecture documentation. !8264 (Pablo Carranza <pablo@gitlab.com>)
+- Sort numbers in build names more intelligently. !8277
+- Show nested groups tab on group page. !8308
+- Rename users with namespace ending with .git. !8309
+- Rename filename to file path in tooltip of file header in merge request diff. !8314
+- About GitLab link in sidebar that links to help page. !8316
+- Merged the 'Groups' and 'Projects' tabs when viewing user profiles. !8323 (James Gregory)
+- re-enable change username button after failure. !8332
+- Darkened hr border color in descriptions because of update of bootstrap. !8333
+- display merge request discussion tab for empty branches. !8347
+- Fix double spaced CI log. !8349 (Jared Deckard <jared.deckard@gmail.com>)
+- Refactored note edit form to improve frontend performance on MR and Issues pages, especially pages with has a lot of discussions in it. !8356
+- Make CTRL+Enter submits a new merge request. !8360 (Saad Shahd)
+- Fixes too short input for placeholder message in commit listing page. !8367
+- Fix typo: seach to search. !8370
+- Adds label to Environments "Date Created". !8376 (Saad Shahd)
+- Convert project setting text into protected branch path link. !8377 (Ken Ding)
+- Precompile all JavaScript fixtures. !8384
+- Use original casing for build action text. !8387
+- Scroll to bottom on build completion if autoscroll was active. !8391
+- Properly handle failed reCAPTCHA on user registration. !8403
+- Changed alerts to be responsive, centered text on smaller viewports. !8424 (Connor Smallman)
+- Pass Gitaly resource path to gitlab-workhorse if Gitaly is enabled. !8440
+- Fixes and Improves CSS and HTML problems in mini pipeline graph and builds dropdown. !8443
+- Don't instrument 405 Grape calls. !8445
+- Change CI template linter textarea with Ace Editor. !8452 (Didem Acet)
+- Removes unneeded `window` declaration in environments related code. !8456
+- API: fix query response for `/projects/:id/issues?milestone="No%20Milestone"`. !8457 (Panagiotis Atmatzidis, David Eisner)
+- Fix broken url on group avatar. !8464 (hogewest)
+- Fixes buttons not being accessible via the keyboard when creating new group. !8469
+- Restore backup correctly when "BACKUP" environment variable is passed. !8477
+- Add new endpoints for Time Tracking. !8483
+- Fix Compare page throws 500 error when any branch/reference is not selected. !8492 (Martin Cabrera)
+- Treat environments matching `production/*` as Production. !8500
+- Hide build artifacts keep button if operation is not allowed. !8501
+- Update the gitlab-markup gem to the version 1.5.1. !8509
+- Remove Lock Icon on Protected Tag. !8513 (Sergey Nikitin)
+- Use cached values to compute total issues count in milestone index pages. !8518
+- Speed up dashboard milestone index by scoping IssuesFinder to user authorized projects. !8524
+- Copy <some text> to clipboard. !8535
+- Check for env[Grape::Env::GRAPE_ROUTING_ARGS] instead of endpoint.route. !8544
+- Fixes builds dropdown making request when clicked to be closed. !8545
+- Fixes pipeline status cell is too wide by adding missing classes in table head cells. !8549
+- Mutate the attribute instead of issuing a write operation to the DB in `ProjectFeaturesCompatibility` concern. !8552
+- Fix links to commits pages on pipelines list page. !8558
+- Ensure updating project settings shows a flash message on success. !8579 (Sandish Chen)
+- Fixes big pipeline and small pipeline width problems and tooltips text being outside the tooltip. !8593
+- Autoresize markdown preview. !8607 (Didem Acet)
+- Link external build badge to its target URL. !8611
+- Adjust ProjectStatistic#repository_size with values saved as MB. !8616
+- Correct User-agent placement in robots.txt. !8623 (Eric Sabelhaus)
+- Record used SSH keys only once per day. !8655
+- Do not generate pipeline branch/tag path if not present. !8658
+- Fix Merge When Pipeline Succeeds immediate merge bug. !8685
+- Fix blame 500 error on invalid path. !25761 (Jeff Stubler)
+- Added animations to issue boards interactions.
+- Check if user can read project before being assigned to issue.
+- Show 'too many changes' message for created merge requests when they are too large.
+- Fix redirect after update file when user has forked project.
+- Parse JIRA issue references even if Issue Tracker is disabled.
+- Made download artifacts button accessible via keyboard by changing it from an anchor tag to an actual button. (Ryan Harris)
+- Make play button on Pipelines page accessible via keyboard. (Ryan Harris)
+- Decreases font-size on login page.
+- Fixed merge request tabs dont move when opening collapsed sidebar.
+- Display project avatars on Admin Area and Projects pages for mobile views. (Ryan Harris)
+- Fix participants margins to fit on one line.
+- 26352 Change Profile settings to User / Settings.
+- Fix Commits API to accept a Project path upon POST.
+- Expire related caches after changing HEAD. (Minqi Pan)
+- Add various hover animations throughout the application.
+- Re-order update steps in the 8.14 -> 8.15 upgrade guide.
+- Move award emoji's out of the discussion tab for merge requests.
+- Synchronize all project authorization refreshing work to prevent race conditions.
+- Remove the project_authorizations.id column.
+- Combined the settings options project members and groups into a single one called members.
+- Change earlier to task_status_short to avoid titlebar line wraps.
+- 25701 standardize text colors.
+- Handle HTTP errors in environment list.
+- Re-add Google Cloud Storage as a backup strategy.
+- Change status colors of runners to better defaults.
+- Added number_with_delimiter to counter on milestone panels. (Ryan Harris)
+- Query external CI statuses in the background.
+- Allow group and project paths when transferring projects via the API.
+- Don't validate environment urls on .gitlab-ci.yml.
+- Fix a Grape deprecation, use `#request_method` instead of `#route_method`.
+- Fill missing authorized projects rows.
+- Allow API query to find projects with dots in their name. (Bruno Melli)
+- Fix import/export wrong user mapping.
+- Removed bottom padding from merge manually from CLI because of repositioning award emoji's.
+- Fix project queued for deletion re-creation tooltip.
+- Fix search group/project filtering to show results.
+- Fix 500 error when POSTing to Users API with optional confirm param.
+- 26504 Fix styling of MR jump to discussion button.
+- Add margin to markdown math blocks.
+- Add hover state to MR comment reply button.
+
## 8.15.4 (2017-01-09)
- Make successful pipeline emails off for watchers. !8176
diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION
index 6085e946503..f0bb29e7638 100644
--- a/GITLAB_WORKHORSE_VERSION
+++ b/GITLAB_WORKHORSE_VERSION
@@ -1 +1 @@
-1.2.1
+1.3.0
diff --git a/VERSION b/VERSION
index 8e9258150a9..5c99c061a47 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-8.16.0-pre
+8.17.0-pre
diff --git a/app/assets/javascripts/droplab/droplab.js b/app/assets/javascripts/droplab/droplab.js
index ed545ec8748..c79f0230951 100644
--- a/app/assets/javascripts/droplab/droplab.js
+++ b/app/assets/javascripts/droplab/droplab.js
@@ -62,6 +62,7 @@ var DropDown = function(list) {
this.list = list;
this.items = [];
this.getItems();
+ this.initTemplateString();
this.addEvents();
this.initialState = list.innerHTML;
};
@@ -72,6 +73,17 @@ Object.assign(DropDown.prototype, {
return this.items;
},
+ initTemplateString: function() {
+ var items = this.items || this.getItems();
+
+ var templateString = '';
+ if(items.length > 0) {
+ templateString = items[items.length - 1].outerHTML;
+ }
+ this.templateString = templateString;
+ return this.templateString;
+ },
+
clickEvent: function(e) {
// climb up the tree to find the LI
var selected = utils.closest(e.target, 'LI');
@@ -111,30 +123,21 @@ Object.assign(DropDown.prototype, {
addData: function(data) {
this.data = (this.data || []).concat(data);
- this.render(data);
+ this.render(this.data);
},
// call render manually on data;
render: function(data){
// debugger
// empty the list first
- var sampleItem;
+ var templateString = this.templateString;
var newChildren = [];
var toAppend;
- for(var i = 0; i < this.items.length; i++) {
- var item = this.items[i];
- sampleItem = item;
- if(item.parentNode && item.parentNode.dataset.hasOwnProperty('dynamic')) {
- item.parentNode.removeChild(item);
- }
- }
-
- newChildren = this.data.map(function(dat){
- var html = utils.t(sampleItem.outerHTML, dat);
+ newChildren = (data ||[]).map(function(dat){
+ var html = utils.t(templateString, dat);
var template = document.createElement('div');
template.innerHTML = html;
- // console.log(template.content)
// Help set the image src template
var imageTags = template.querySelectorAll('img[data-src]');
@@ -156,7 +159,7 @@ Object.assign(DropDown.prototype, {
if(toAppend) {
toAppend.innerHTML = newChildren.join('');
} else {
- this.list.innerHTML = newChildren.join('');
+ this.list.innerHTML = newChildren.join('');
}
},
@@ -173,10 +176,7 @@ Object.assign(DropDown.prototype, {
},
destroy: function() {
- if (!this.hidden) {
- this.hide();
- }
-
+ this.hide();
this.list.removeEventListener('click', this.clickWrapper);
}
});
@@ -278,7 +278,7 @@ require('./window')(function(w){
self.hooks[i].list.hide();
}
}.bind(this);
- w.addEventListener('click', this.windowClickedWrapper);
+ document.addEventListener('click', this.windowClickedWrapper);
},
removeEvents: function(){
@@ -307,7 +307,7 @@ require('./window')(function(w){
if(!list){
list = document.querySelector(hook.dataset[utils.toDataCamelCase(DATA_TRIGGER)]);
}
-
+
if(hook) {
if(hook.tagName === 'A' || hook.tagName === 'BUTTON') {
this.hooks.push(new HookButton(hook, list, plugins, config));
@@ -462,6 +462,8 @@ Object.assign(HookInput.prototype, {
var self = this;
this.mousedown = function mousedown(e) {
+ if(self.hasRemovedEvents) return;
+
var mouseEvent = new CustomEvent('mousedown.dl', {
detail: {
hook: self,
@@ -474,6 +476,8 @@ Object.assign(HookInput.prototype, {
}
this.input = function input(e) {
+ if(self.hasRemovedEvents) return;
+
var inputEvent = new CustomEvent('input.dl', {
detail: {
hook: self,
@@ -487,10 +491,14 @@ Object.assign(HookInput.prototype, {
}
this.keyup = function keyup(e) {
+ if(self.hasRemovedEvents) return;
+
keyEvent(e, 'keyup.dl');
}
this.keydown = function keydown(e) {
+ if(self.hasRemovedEvents) return;
+
keyEvent(e, 'keydown.dl');
}
@@ -520,7 +528,8 @@ Object.assign(HookInput.prototype, {
this.trigger.addEventListener('keydown', this.keydown);
},
- removeEvents: function(){
+ removeEvents: function() {
+ this.hasRemovedEvents = true;
this.trigger.removeEventListener('mousedown', this.mousedown);
this.trigger.removeEventListener('input', this.input);
this.trigger.removeEventListener('keyup', this.keyup);
@@ -578,7 +587,7 @@ require('./window')(function(w){
var listItems = removeHighlight(list);
if(currentIndex>0){
if(!listItems[currentIndex-1]){
- currentIndex = currentIndex-1;
+ currentIndex = currentIndex-1;
}
listItems[currentIndex-1].classList.add('dropdown-active');
}
@@ -630,7 +639,7 @@ require('./window')(function(w){
return;
}
if(currentKey === 'ArrowUp') {
- isUpArrow = true;
+ isUpArrow = true;
}
if(currentKey === 'ArrowDown') {
isDownArrow = true;
@@ -668,16 +677,16 @@ var camelize = function(str) {
};
var closest = function(thisTag, stopTag) {
- while(thisTag.tagName !== stopTag && thisTag.tagName !== 'HTML'){
+ while(thisTag && thisTag.tagName !== stopTag && thisTag.tagName !== 'HTML'){
thisTag = thisTag.parentNode;
}
return thisTag;
};
var isDropDownParts = function(target) {
- if(target.tagName === 'HTML') { return false; }
+ if(!target || target.tagName === 'HTML') { return false; }
return (
- target.hasAttribute(DATA_TRIGGER) ||
+ target.hasAttribute(DATA_TRIGGER) ||
target.hasAttribute(DATA_DROPDOWN)
);
};
diff --git a/app/assets/javascripts/extensions/custom_event.js.es6 b/app/assets/javascripts/extensions/custom_event.js.es6
new file mode 100644
index 00000000000..abedae4c1c7
--- /dev/null
+++ b/app/assets/javascripts/extensions/custom_event.js.es6
@@ -0,0 +1,12 @@
+/* global CustomEvent */
+/* eslint-disable no-global-assign */
+
+// Custom event support for IE
+CustomEvent = function CustomEvent(event, parameters) {
+ const params = parameters || { bubbles: false, cancelable: false, detail: undefined };
+ const evt = document.createEvent('CustomEvent');
+ evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
+ return evt;
+};
+
+CustomEvent.prototype = window.Event.prototype;
diff --git a/app/assets/javascripts/filtered_search/dropdown_hint.js.es6 b/app/assets/javascripts/filtered_search/dropdown_hint.js.es6
index 63c20f57520..f4ec3b206cc 100644
--- a/app/assets/javascripts/filtered_search/dropdown_hint.js.es6
+++ b/app/assets/javascripts/filtered_search/dropdown_hint.js.es6
@@ -9,7 +9,7 @@
this.config = {
droplabFilter: {
template: 'hint',
- filterFunction: gl.DropdownUtils.filterHint,
+ filterFunction: gl.DropdownUtils.filterHint.bind(null, input),
},
};
}
diff --git a/app/assets/javascripts/filtered_search/dropdown_non_user.js.es6 b/app/assets/javascripts/filtered_search/dropdown_non_user.js.es6
index f06c3fc9c6f..13cbec1be4a 100644
--- a/app/assets/javascripts/filtered_search/dropdown_non_user.js.es6
+++ b/app/assets/javascripts/filtered_search/dropdown_non_user.js.es6
@@ -15,7 +15,7 @@
loadingTemplate: this.loadingTemplate,
},
droplabFilter: {
- filterFunction: gl.DropdownUtils.filterWithSymbol.bind(null, this.symbol),
+ filterFunction: gl.DropdownUtils.filterWithSymbol.bind(null, this.symbol, input),
},
};
}
diff --git a/app/assets/javascripts/filtered_search/dropdown_user.js.es6 b/app/assets/javascripts/filtered_search/dropdown_user.js.es6
index e80d266ae89..7bf199d9274 100644
--- a/app/assets/javascripts/filtered_search/dropdown_user.js.es6
+++ b/app/assets/javascripts/filtered_search/dropdown_user.js.es6
@@ -37,7 +37,7 @@
}
getSearchInput() {
- const query = this.input.value.trim();
+ const query = gl.DropdownUtils.getSearchInput(this.input);
const { lastToken } = gl.FilteredSearchTokenizer.processTokens(query);
return lastToken.value || '';
diff --git a/app/assets/javascripts/filtered_search/dropdown_utils.js.es6 b/app/assets/javascripts/filtered_search/dropdown_utils.js.es6
index c27ef3042d1..443ac222f70 100644
--- a/app/assets/javascripts/filtered_search/dropdown_utils.js.es6
+++ b/app/assets/javascripts/filtered_search/dropdown_utils.js.es6
@@ -20,17 +20,15 @@
return escapedText;
}
- static filterWithSymbol(filterSymbol, item, query) {
+ static filterWithSymbol(filterSymbol, input, item) {
const updatedItem = item;
+ const query = gl.DropdownUtils.getSearchInput(input);
const { lastToken, searchToken } = gl.FilteredSearchTokenizer.processTokens(query);
if (lastToken !== searchToken) {
const title = updatedItem.title.toLowerCase();
let value = lastToken.value.toLowerCase();
-
- if ((value[0] === '"' || value[0] === '\'') && title.indexOf(' ') !== -1) {
- value = value.slice(1);
- }
+ value = value.replace(/"(.*?)"/g, str => str.slice(1).slice(0, -1));
// Eg. filterSymbol = ~ for labels
const matchWithoutSymbol = lastToken.symbol === filterSymbol && title.indexOf(value) !== -1;
@@ -44,8 +42,9 @@
return updatedItem;
}
- static filterHint(item, query) {
+ static filterHint(input, item) {
const updatedItem = item;
+ const query = gl.DropdownUtils.getSearchInput(input);
let { lastToken } = gl.FilteredSearchTokenizer.processTokens(query);
lastToken = lastToken.key || lastToken || '';
@@ -72,6 +71,48 @@
// Return boolean based on whether it was set
return dataValue !== null;
}
+
+ static getSearchInput(filteredSearchInput) {
+ const inputValue = filteredSearchInput.value;
+ const { right } = gl.DropdownUtils.getInputSelectionPosition(filteredSearchInput);
+
+ return inputValue.slice(0, right);
+ }
+
+ static getInputSelectionPosition(input) {
+ const selectionStart = input.selectionStart;
+ let inputValue = input.value;
+ // Replace all spaces inside quote marks with underscores
+ // This helps with matching the beginning & end of a token:key
+ inputValue = inputValue.replace(/"(.*?)"/g, str => str.replace(/\s/g, '_'));
+
+ // Get the right position for the word selected
+ // Regex matches first space
+ let right = inputValue.slice(selectionStart).search(/\s/);
+
+ if (right >= 0) {
+ right += selectionStart;
+ } else if (right < 0) {
+ right = inputValue.length;
+ }
+
+ // Get the left position for the word selected
+ // Regex matches last non-whitespace character
+ let left = inputValue.slice(0, right).search(/\S+$/);
+
+ if (selectionStart === 0) {
+ left = 0;
+ } else if (selectionStart === inputValue.length && left < 0) {
+ left = inputValue.length;
+ } else if (left < 0) {
+ left = selectionStart;
+ }
+
+ return {
+ left,
+ right,
+ };
+ }
}
window.gl = window.gl || {};
diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js.es6
index 886d8113f4a..9128ea907b3 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js.es6
+++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js.es6
@@ -78,7 +78,10 @@
dispatchInputEvent() {
// Propogate input change to FilteredSearchDropdownManager
// so that it can determine which dropdowns to open
- this.input.dispatchEvent(new Event('input'));
+ this.input.dispatchEvent(new CustomEvent('input', {
+ bubbles: true,
+ cancelable: true,
+ }));
}
hideDropdown() {
diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js.es6
index 1cd0483877a..408a0dfd768 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js.es6
+++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js.es6
@@ -57,28 +57,25 @@
static addWordToInput(tokenName, tokenValue = '') {
const input = document.querySelector('.filtered-search');
+ const inputValue = input.value;
const word = `${tokenName}:${tokenValue}`;
- const { lastToken, searchToken } = gl.FilteredSearchTokenizer.processTokens(input.value);
- const lastSearchToken = searchToken.split(' ').last();
- const lastInputCharacter = input.value[input.value.length - 1];
- const lastInputTrimmedCharacter = input.value.trim()[input.value.trim().length - 1];
-
- // Remove the typed tokenName
- if (word.indexOf(lastSearchToken) === 0 && searchToken !== '') {
- // Remove spaces after the colon
- if (lastInputCharacter === ' ' && lastInputTrimmedCharacter === ':') {
- input.value = input.value.trim();
- }
-
- input.value = input.value.slice(0, -1 * lastSearchToken.length);
- } else if (lastInputCharacter !== ' ' || (lastToken && lastToken.value[lastToken.value.length - 1] === ' ')) {
- // Remove the existing tokenValue
- const lastTokenString = `${lastToken.key}:${lastToken.symbol}${lastToken.value}`;
- input.value = input.value.slice(0, -1 * lastTokenString.length);
- }
+ // Get the string to replace
+ const selectionStart = input.selectionStart;
+ const { left, right } = gl.DropdownUtils.getInputSelectionPosition(input);
+
+ input.value = `${inputValue.substr(0, left)}${word}${inputValue.substr(right)}`;
+ gl.FilteredSearchDropdownManager.updateInputCaretPosition(selectionStart, input);
+ }
+
+ static updateInputCaretPosition(selectionStart, input) {
+ // Reset the position
+ // Sometimes can end up at end of input
+ input.setSelectionRange(selectionStart, selectionStart);
- input.value += word;
+ const { right } = gl.DropdownUtils.getInputSelectionPosition(input);
+
+ input.setSelectionRange(right, right);
}
updateCurrentDropdownOffset() {
@@ -90,9 +87,18 @@
this.font = window.getComputedStyle(this.filteredSearchInput).font;
}
+ const input = this.filteredSearchInput;
+ const inputText = input.value.slice(0, input.selectionStart);
const filterIconPadding = 27;
- const offset = gl.text
- .getTextWidth(this.filteredSearchInput.value, this.font) + filterIconPadding;
+ let offset = gl.text.getTextWidth(inputText, this.font) + filterIconPadding;
+
+ const currentDropdownWidth = this.mapping[key].element.clientWidth === 0 ? 200 :
+ this.mapping[key].element.clientWidth;
+ const offsetMaxWidth = this.filteredSearchInput.clientWidth - currentDropdownWidth;
+
+ if (offsetMaxWidth < offset) {
+ offset = offsetMaxWidth;
+ }
this.mapping[key].reference.setOffset(offset);
}
@@ -148,9 +154,9 @@
setDropdown() {
const { lastToken, searchToken } = this.tokenizer
- .processTokens(this.filteredSearchInput.value);
+ .processTokens(gl.DropdownUtils.getSearchInput(this.filteredSearchInput));
- if (this.filteredSearchInput.value.split('').last() === ' ') {
+ if (this.currentDropdown) {
this.updateCurrentDropdownOffset();
}
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6
index ffd0d7e9cba..c7b72b36561 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6
+++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6
@@ -30,11 +30,14 @@
this.checkForEnterWrapper = this.checkForEnter.bind(this);
this.clearSearchWrapper = this.clearSearch.bind(this);
this.checkForBackspaceWrapper = this.checkForBackspace.bind(this);
+ this.tokenChange = this.tokenChange.bind(this);
this.filteredSearchInput.addEventListener('input', this.setDropdownWrapper);
this.filteredSearchInput.addEventListener('input', this.toggleClearSearchButtonWrapper);
this.filteredSearchInput.addEventListener('keydown', this.checkForEnterWrapper);
this.filteredSearchInput.addEventListener('keyup', this.checkForBackspaceWrapper);
+ this.filteredSearchInput.addEventListener('click', this.tokenChange);
+ this.filteredSearchInput.addEventListener('keyup', this.tokenChange);
this.clearSearchButton.addEventListener('click', this.clearSearchWrapper);
}
@@ -43,6 +46,8 @@
this.filteredSearchInput.removeEventListener('input', this.toggleClearSearchButtonWrapper);
this.filteredSearchInput.removeEventListener('keydown', this.checkForEnterWrapper);
this.filteredSearchInput.removeEventListener('keyup', this.checkForBackspaceWrapper);
+ this.filteredSearchInput.removeEventListener('click', this.tokenChange);
+ this.filteredSearchInput.removeEventListener('keyup', this.tokenChange);
this.clearSearchButton.removeEventListener('click', this.clearSearchWrapper);
}
@@ -85,6 +90,7 @@
loadSearchParamsFromURL() {
const params = gl.utils.getUrlParamsArray();
+ const usernameParams = this.getUsernameParams();
const inputValues = [];
params.forEach((p) => {
@@ -115,6 +121,16 @@
}
inputValues.push(`${sanitizedKey}:${symbol}${quotationsToUse}${sanitizedValue}${quotationsToUse}`);
+ } else if (!match && keyParam === 'assignee_id') {
+ const id = parseInt(value, 10);
+ if (usernameParams[id]) {
+ inputValues.push(`assignee:@${usernameParams[id]}`);
+ }
+ } else if (!match && keyParam === 'author_id') {
+ const id = parseInt(value, 10);
+ if (usernameParams[id]) {
+ inputValues.push(`author:@${usernameParams[id]}`);
+ }
} else if (!match && keyParam === 'search') {
inputValues.push(sanitizedValue);
}
@@ -164,6 +180,27 @@
Turbolinks.visit(`?scope=all&utf8=✓&${paths.join('&')}`);
}
+
+ getUsernameParams() {
+ const usernamesById = {};
+ try {
+ const attribute = this.filteredSearchInput.getAttribute('data-username-params');
+ JSON.parse(attribute).forEach((user) => {
+ usernamesById[user.id] = user.username;
+ });
+ } catch (e) {
+ // do nothing
+ }
+ return usernamesById;
+ }
+
+ tokenChange() {
+ const dropdown = this.dropdownManager.mapping[this.dropdownManager.currentDropdown];
+ const currentDropdownRef = dropdown.reference;
+
+ this.setDropdownWrapper();
+ currentDropdownRef.dispatchInputEvent();
+ }
}
window.gl = window.gl || {};
diff --git a/app/assets/javascripts/group_avatar.js b/app/assets/javascripts/group_avatar.js
index 5247b2a08f7..10dfd05fe3c 100644
--- a/app/assets/javascripts/group_avatar.js
+++ b/app/assets/javascripts/group_avatar.js
@@ -2,12 +2,12 @@
(function() {
this.GroupAvatar = (function() {
function GroupAvatar() {
- $('.js-choose-group-avatar-button').bind("click", function() {
+ $('.js-choose-group-avatar-button').on("click", function() {
var form;
form = $(this).closest("form");
return form.find(".js-group-avatar-input").click();
});
- $('.js-group-avatar-input').bind("change", function() {
+ $('.js-group-avatar-input').on("change", function() {
var filename, form;
form = $(this).closest("form");
filename = $(this).val().replace(/^.*[\\\/]/, '');
diff --git a/app/assets/javascripts/merge_request_widget.js.es6 b/app/assets/javascripts/merge_request_widget.js.es6
index 7a315e43667..7cc319e2f4e 100644
--- a/app/assets/javascripts/merge_request_widget.js.es6
+++ b/app/assets/javascripts/merge_request_widget.js.es6
@@ -126,7 +126,9 @@
MergeRequestWidget.prototype.getMergeStatus = function() {
return $.get(this.opts.merge_check_url, function(data) {
- return $('.mr-state-widget').replaceWith(data);
+ var $html = $(data);
+ $('.mr-widget-body').replaceWith($html.find('.mr-widget-body'));
+ $('.mr-widget-footer').replaceWith($html.find('.mr-widget-footer'));
});
};
diff --git a/app/assets/javascripts/merge_request_widget/ci_bundle.js.es6 b/app/assets/javascripts/merge_request_widget/ci_bundle.js.es6
index 2b074994b4a..5969d2ba56b 100644
--- a/app/assets/javascripts/merge_request_widget/ci_bundle.js.es6
+++ b/app/assets/javascripts/merge_request_widget/ci_bundle.js.es6
@@ -8,31 +8,42 @@
* temporarily.
* */
- if ($('.accept-mr-form').length) {
- $('.accept-mr-form').on('ajax:send', () => {
- $('.accept-mr-form :input').disable();
- });
+ $(document)
+ .off('ajax:send', '.accept-mr-form')
+ .on('ajax:send', '.accept-mr-form', () => {
+ $('.accept-mr-form :input').disable();
+ });
- $('.accept_merge_request').on('click', () => {
- $('.js-merge-button').html('<i class="fa fa-spinner fa-spin"></i> Merge in progress');
- });
+ $(document)
+ .off('click', '.accept_merge_request')
+ .on('click', '.accept_merge_request', () => {
+ $('.js-merge-button').html('<i class="fa fa-spinner fa-spin"></i> Merge in progress');
+ });
- $('.merge_when_build_succeeds').on('click', () => {
- $('#merge_when_build_succeeds').val('1');
- });
+ $(document)
+ .off('click', '.merge_when_build_succeeds')
+ .on('click', '.merge_when_build_succeeds', () => {
+ $('#merge_when_build_succeeds').val('1');
+ });
- $('.js-merge-dropdown a').on('click', (e) => {
- e.preventDefault();
- $(this).closest('form').submit();
- });
- } else if ($('.rebase-in-progress').length) {
+ $(document)
+ .off('click', '.js-merge-dropdown a')
+ .on('click', '.js-merge-dropdown a', (e) => {
+ e.preventDefault();
+ $(e.target).closest('form').submit();
+ });
+ if ($('.rebase-in-progress').length) {
merge_request_widget.rebaseInProgress();
} else if ($('.rebase-mr-form').length) {
- $('.rebase-mr-form').on('ajax:send', () => {
+ $(document)
+ .off('ajax:send', '.rebase-mr-form')
+ .on('ajax:send', '.rebase-mr-form', () => {
$('.rebase-mr-form :input').disable();
});
- $('.js-rebase-button').on('click', () => {
+ $(document)
+ .off('click', '.js-rebase-button')
+ .on('click', '.js-rebase-button', () => {
$('.js-rebase-button').html("<i class='fa fa-spinner fa-spin'></i> Rebase in progress");
});
} else {
diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6
index 32973132174..4e85f16ebc5 100644
--- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6
+++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6
@@ -1,5 +1,5 @@
/* global Vue, Flash, gl */
-/* eslint-disable no-param-reassign, no-bitwise */
+/* eslint-disable no-param-reassign */
((gl) => {
gl.VueStage = Vue.extend({
@@ -9,7 +9,20 @@
spinner: '<span class="fa fa-spinner fa-spin"></span>',
};
},
- props: ['stage', 'svgs', 'match'],
+ props: {
+ stage: {
+ type: Object,
+ required: true,
+ },
+ svgs: {
+ type: DOMStringMap,
+ required: true,
+ },
+ match: {
+ type: Function,
+ required: true,
+ },
+ },
methods: {
fetchBuilds(e) {
const areaExpanded = e.currentTarget.attributes['aria-expanded'];
@@ -24,6 +37,18 @@
return flash;
});
},
+ keepGraph(e) {
+ const { target } = e;
+
+ if (target.className.indexOf('js-ci-action-icon') >= 0) return null;
+
+ if (
+ target.parentElement &&
+ (target.parentElement.className.indexOf('js-ci-action-icon') >= 0)
+ ) return null;
+
+ return e.stopPropagation();
+ },
},
computed: {
buildsOrSpinner() {
@@ -64,7 +89,7 @@
<ul class="dropdown-menu mini-pipeline-graph-dropdown-menu js-builds-dropdown-container">
<div class="arrow-up"></div>
<div
- @click=''
+ @click='keepGraph($event)'
:class="dropdownClass"
class="js-builds-dropdown-list scrollable-menu"
v-html="buildsOrSpinner"
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 324c6cec96a..93cc5a8cf0a 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -377,6 +377,10 @@
display: inline-block;
padding: 5px;
+ &:nth-of-type(7n) {
+ padding-right: 0;
+ }
+
.author_link {
display: block;
}
diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb
index 0ae8ff98009..b668a9331e7 100644
--- a/app/controllers/projects/hooks_controller.rb
+++ b/app/controllers/projects/hooks_controller.rb
@@ -6,21 +6,15 @@ class Projects::HooksController < Projects::ApplicationController
layout "project_settings"
- def index
- @hooks = @project.hooks
- @hook = ProjectHook.new
- end
-
def create
@hook = @project.hooks.new(hook_params)
@hook.save
- if @hook.valid?
- redirect_to namespace_project_hooks_path(@project.namespace, @project)
- else
+ unless @hook.valid?
@hooks = @project.hooks.select(&:persisted?)
- render :index
+ flash[:alert] = @hook.errors.full_messages.join.html_safe
end
+ redirect_to namespace_project_settings_integrations_path(@project.namespace, @project)
end
def test
@@ -44,7 +38,7 @@ class Projects::HooksController < Projects::ApplicationController
def destroy
hook.destroy
- redirect_to namespace_project_hooks_path(@project.namespace, @project)
+ redirect_to namespace_project_settings_integrations_path(@project.namespace, @project)
end
private
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 2beb0df8a07..8472ceca329 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -33,6 +33,18 @@ class Projects::IssuesController < Projects::ApplicationController
@labels = LabelsFinder.new(current_user, project_id: @project.id, title: params[:label_name]).execute
end
+ @users = []
+
+ if params[:assignee_id].present?
+ assignee = User.find_by_id(params[:assignee_id])
+ @users.push(assignee) if assignee
+ end
+
+ if params[:author_id].present?
+ author = User.find_by_id(params[:author_id])
+ @users.push(author) if author
+ end
+
respond_to do |format|
format.html
format.atom { render layout: false }
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index 30c2a5d9982..17cb1d5be24 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -9,10 +9,6 @@ class Projects::ServicesController < Projects::ApplicationController
layout "project_settings"
- def index
- @services = @project.find_or_initialize_services
- end
-
def edit
end
diff --git a/app/controllers/projects/settings/integrations_controller.rb b/app/controllers/projects/settings/integrations_controller.rb
new file mode 100644
index 00000000000..fb2a4837735
--- /dev/null
+++ b/app/controllers/projects/settings/integrations_controller.rb
@@ -0,0 +1,18 @@
+module Projects
+ module Settings
+ class IntegrationsController < Projects::ApplicationController
+ include ServiceParams
+
+ before_action :authorize_admin_project!
+ layout "project_settings"
+
+ def show
+ @hooks = @project.hooks
+ @hook = ProjectHook.new
+
+ # Services
+ @services = @project.find_or_initialize_services
+ end
+ end
+ end
+end
diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb
index 5742fec4458..2159e4ce21a 100644
--- a/app/helpers/gitlab_routing_helper.rb
+++ b/app/helpers/gitlab_routing_helper.rb
@@ -208,6 +208,10 @@ module GitlabRoutingHelper
end
# Settings
+ def project_settings_integrations_path(project, *args)
+ namespace_project_settings_integrations_path(project.namespace, project, *args)
+ end
+
def project_settings_members_path(project, *args)
namespace_project_settings_members_path(project.namespace, project, *args)
end
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 6e58a1878c8..ed1843ba005 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -126,9 +126,11 @@ module Ci
end
def tick_runner_queue
- new_update = SecureRandom.hex
- Gitlab::Redis.with { |redis| redis.set(runner_queue_key, new_update, ex: RUNNER_QUEUE_EXPIRY_TIME) }
- new_update
+ SecureRandom.hex.tap do |new_update|
+ Gitlab::Redis.with do |redis|
+ redis.set(runner_queue_key, new_update, ex: RUNNER_QUEUE_EXPIRY_TIME)
+ end
+ end
end
def ensure_runner_queue_value
diff --git a/app/models/key.rb b/app/models/key.rb
index 8be29c697f1..9c74ca84753 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -4,6 +4,8 @@ class Key < ActiveRecord::Base
include AfterCommitQueue
include Sortable
+ LAST_USED_AT_REFRESH_TIME = 1.day.to_i
+
belongs_to :user
before_validation :generate_fingerprint
@@ -50,7 +52,10 @@ class Key < ActiveRecord::Base
end
def update_last_used_at
- UseKeyWorker.perform_async(self.id)
+ lease = Gitlab::ExclusiveLease.new("key_update_last_used_at:#{id}", timeout: LAST_USED_AT_REFRESH_TIME)
+ return unless lease.try_obtain
+
+ UseKeyWorker.perform_async(id)
end
def add_to_shell
diff --git a/app/serializers/pipeline_entity.rb b/app/serializers/pipeline_entity.rb
index d04a4990cb0..61f0f11d7d2 100644
--- a/app/serializers/pipeline_entity.rb
+++ b/app/serializers/pipeline_entity.rb
@@ -40,10 +40,12 @@ class PipelineEntity < Grape::Entity
end
expose :path do |pipeline|
- namespace_project_tree_path(
- pipeline.project.namespace,
- pipeline.project,
- id: pipeline.ref)
+ if pipeline.ref
+ namespace_project_tree_path(
+ pipeline.project.namespace,
+ pipeline.project,
+ id: pipeline.ref)
+ end
end
expose :tag?, as: :tag
diff --git a/app/services/ci/update_build_queue_service.rb b/app/services/ci/update_build_queue_service.rb
index 2e901016666..152c8ae5006 100644
--- a/app/services/ci/update_build_queue_service.rb
+++ b/app/services/ci/update_build_queue_service.rb
@@ -6,6 +6,14 @@ module Ci
runner.tick_runner_queue
end
end
+
+ return unless build.project.shared_runners_enabled?
+
+ Ci::Runner.shared.each do |runner|
+ if runner.can_pick?(build)
+ runner.tick_runner_queue
+ end
+ end
end
end
end
diff --git a/app/views/layouts/nav/_project_settings.html.haml b/app/views/layouts/nav/_project_settings.html.haml
index 0fb2bb460cb..c6df66d2c3c 100644
--- a/app/views/layouts/nav/_project_settings.html.haml
+++ b/app/views/layouts/nav/_project_settings.html.haml
@@ -8,14 +8,10 @@
= link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys' do
%span
Deploy Keys
- = nav_link(controller: :hooks) do
- = link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Webhooks' do
+ = nav_link(controller: :integrations) do
+ = link_to namespace_project_settings_integrations_path(@project.namespace, @project), title: 'Integrations' do
%span
- Webhooks
- = nav_link(controller: :services) do
- = link_to namespace_project_services_path(@project.namespace, @project), title: 'Services' do
- %span
- Services
+ Integrations
= nav_link(controller: :protected_branches) do
= link_to namespace_project_protected_branches_path(@project.namespace, @project), title: 'Protected Branches' do
%span
diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/_index.html.haml
index 8faad351463..8faad351463 100644
--- a/app/views/projects/hooks/index.html.haml
+++ b/app/views/projects/hooks/_index.html.haml
diff --git a/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml b/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml
index 072d01d144e..f70cd09c5f4 100644
--- a/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml
+++ b/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml
@@ -1,3 +1,6 @@
+- content_for :page_specific_javascripts do
+ = page_specific_javascript_tag('merge_request_widget/ci_bundle.js')
+
%h4
Set by #{link_to_member(@project, @merge_request.merge_user, avatar: true)}
to be merged automatically when the pipeline succeeds.
diff --git a/app/views/projects/services/index.html.haml b/app/views/projects/services/_index.html.haml
index 66fd3029dc9..964133504e6 100644
--- a/app/views/projects/services/index.html.haml
+++ b/app/views/projects/services/_index.html.haml
@@ -1,5 +1,3 @@
-- page_title "Services"
-
.row.prepend-top-default.append-bottom-default
.col-lg-3
%h4.prepend-top-0
diff --git a/app/views/projects/hooks/_project_hook.html.haml b/app/views/projects/settings/integrations/_project_hook.html.haml
index ceabe2eab3d..ceabe2eab3d 100644
--- a/app/views/projects/hooks/_project_hook.html.haml
+++ b/app/views/projects/settings/integrations/_project_hook.html.haml
diff --git a/app/views/projects/settings/integrations/show.html.haml b/app/views/projects/settings/integrations/show.html.haml
new file mode 100644
index 00000000000..aa38a889cdd
--- /dev/null
+++ b/app/views/projects/settings/integrations/show.html.haml
@@ -0,0 +1,3 @@
+- page_title 'Integrations'
+= render 'projects/hooks/index'
+= render 'projects/services/index'
diff --git a/app/views/shared/_choose_group_avatar_button.html.haml b/app/views/shared/_choose_group_avatar_button.html.haml
index ee043910548..94295970acf 100644
--- a/app/views/shared/_choose_group_avatar_button.html.haml
+++ b/app/views/shared/_choose_group_avatar_button.html.haml
@@ -1,4 +1,4 @@
-%button.choose-btn.btn.btn-sm.js-choose-group-avatar-button
+%button.choose-btn.btn.btn-sm.js-choose-group-avatar-button{ type: 'button' }
%i.fa.fa-paperclip
%span Choose File ...
&nbsp;
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 8d7b1d616f4..44152319736 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -11,7 +11,7 @@
class: "check_all_issues left"
.issues-other-filters.filtered-search-container
.filtered-search-input-container
- %input.form-control.filtered-search{ placeholder: 'Search or filter results...', 'data-id' => 'filtered-search', 'data-project-id' => @project.id }
+ %input.form-control.filtered-search{ placeholder: 'Search or filter results...', 'data-id' => 'filtered-search', 'data-project-id' => @project.id, 'data-username-params' => @users.to_json(only: [:id, :username]) }
= icon('filter')
%button.clear-search.hidden{ type: 'button' }
= icon('times')
@@ -47,6 +47,10 @@
%li.filter-dropdown-item{ 'data-value' => 'none' }
%button.btn.btn-link
No Assignee
+ - if current_user
+ %li.filter-dropdown-item{ 'data-value' => current_user.to_reference }
+ %button.btn.btn-link
+ Assigned to me
%li.divider
%ul.filter-dropdown{ 'data-dynamic' => true, 'data-dropdown' => true }
%li.filter-dropdown-item
@@ -125,3 +129,13 @@
event.preventDefault();
Turbolinks.visit(this.action + '&' + $(this).serialize());
});
+
+ $(document).off('page:restore').on('page:restore', function (event) {
+ if (gl.FilteredSearchManager) {
+ new gl.FilteredSearchManager();
+ }
+ Issuable.init();
+ new gl.IssuableBulkActions({
+ prefixId: 'issue_',
+ });
+ });
diff --git a/app/views/shared/web_hooks/_form.html.haml b/app/views/shared/web_hooks/_form.html.haml
index 5d659eb83a9..13586a5a12a 100644
--- a/app/views/shared/web_hooks/_form.html.haml
+++ b/app/views/shared/web_hooks/_form.html.haml
@@ -1,6 +1,3 @@
-- page_title "Webhooks"
-- context_title = @project ? 'project' : 'group'
-
.row.prepend-top-default
.col-lg-3
%h4.prepend-top-0
diff --git a/changelogs/unreleased/18786-go-to-a-project-order.yml b/changelogs/unreleased/18786-go-to-a-project-order.yml
deleted file mode 100644
index 1b9e246d1a7..00000000000
--- a/changelogs/unreleased/18786-go-to-a-project-order.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Go to a project order
-merge_request: 7737
-author: Jacopo Beschi @jacopo-beschi
diff --git a/changelogs/unreleased/19086-double-newline.yml b/changelogs/unreleased/19086-double-newline.yml
deleted file mode 100644
index dd9b58920fb..00000000000
--- a/changelogs/unreleased/19086-double-newline.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix double spaced CI log
-merge_request: 8349
-author: Jared Deckard <jared.deckard@gmail.com>
diff --git a/changelogs/unreleased/19966-api-call-to-move-project-to-different-group-fails-when-using-group-and-project-names-instead-of-id.yml b/changelogs/unreleased/19966-api-call-to-move-project-to-different-group-fails-when-using-group-and-project-names-instead-of-id.yml
deleted file mode 100644
index 61cf047026b..00000000000
--- a/changelogs/unreleased/19966-api-call-to-move-project-to-different-group-fails-when-using-group-and-project-names-instead-of-id.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow group and project paths when transferring projects via the API
-merge_request:
-author:
diff --git a/changelogs/unreleased/19988-prevent-empty-pagination-when-list-not-empty.yml b/changelogs/unreleased/19988-prevent-empty-pagination-when-list-not-empty.yml
deleted file mode 100644
index 5570ede4a9a..00000000000
--- a/changelogs/unreleased/19988-prevent-empty-pagination-when-list-not-empty.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Prevent empty pagination when list is not empty
-merge_request: 8172
-author:
diff --git a/changelogs/unreleased/21135-resolve-these-conflicts-link-is-too-subtle.yml b/changelogs/unreleased/21135-resolve-these-conflicts-link-is-too-subtle.yml
deleted file mode 100644
index 574c322803c..00000000000
--- a/changelogs/unreleased/21135-resolve-these-conflicts-link-is-too-subtle.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Improve visibility of "Resolve conflicts" and "Merge locally" actions
-merge_request: 8229
-author:
diff --git a/changelogs/unreleased/21698-redis-runner-last-build.yml b/changelogs/unreleased/21698-redis-runner-last-build.yml
deleted file mode 100644
index 2aba3c353a3..00000000000
--- a/changelogs/unreleased/21698-redis-runner-last-build.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Reduce DB-load for build-queues by storing last_update in Redis
-merge_request: 8084
-author:
diff --git a/changelogs/unreleased/22111-remove-lock-icon-on-protected-tag.yml b/changelogs/unreleased/22111-remove-lock-icon-on-protected-tag.yml
deleted file mode 100644
index e4f7c1b7762..00000000000
--- a/changelogs/unreleased/22111-remove-lock-icon-on-protected-tag.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove Lock Icon on Protected Tag
-merge_request: 8513
-author: Sergey Nikitin
diff --git a/changelogs/unreleased/24032-changed-visibility-level-to-public-but-project-is-not-public.yml b/changelogs/unreleased/24032-changed-visibility-level-to-public-but-project-is-not-public.yml
deleted file mode 100644
index 875106d7dd5..00000000000
--- a/changelogs/unreleased/24032-changed-visibility-level-to-public-but-project-is-not-public.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Updated project visibility settings UX
-merge_request: 7645
-author:
diff --git a/changelogs/unreleased/24139-production-wildcard-for-cycle-analytics.yml b/changelogs/unreleased/24139-production-wildcard-for-cycle-analytics.yml
deleted file mode 100644
index 83cf3670ec0..00000000000
--- a/changelogs/unreleased/24139-production-wildcard-for-cycle-analytics.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Treat environments matching `production/*` as Production
-merge_request: 8500
-author:
diff --git a/changelogs/unreleased/24185-legacy-ci-status-reactive-cache.yml b/changelogs/unreleased/24185-legacy-ci-status-reactive-cache.yml
deleted file mode 100644
index 09ff63a44fb..00000000000
--- a/changelogs/unreleased/24185-legacy-ci-status-reactive-cache.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Query external CI statuses in the background
-merge_request:
-author:
diff --git a/changelogs/unreleased/24820-buttons-in-the-branches-page-are-stacking-on-top-of-each-other-depending-on-the-selected-filter.yml b/changelogs/unreleased/24820-buttons-in-the-branches-page-are-stacking-on-top-of-each-other-depending-on-the-selected-filter.yml
deleted file mode 100644
index fac7697ede1..00000000000
--- a/changelogs/unreleased/24820-buttons-in-the-branches-page-are-stacking-on-top-of-each-other-depending-on-the-selected-filter.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: fix button layout issue on branches page
-merge_request: 8074
-author:
diff --git a/changelogs/unreleased/24876-page-jumps-to-wrong-position-when-clicking-a-comment-anchor.yml b/changelogs/unreleased/24876-page-jumps-to-wrong-position-when-clicking-a-comment-anchor.yml
deleted file mode 100644
index c31c89dc4bc..00000000000
--- a/changelogs/unreleased/24876-page-jumps-to-wrong-position-when-clicking-a-comment-anchor.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: ensure permalinks scroll to correct position on multiple clicks
-merge_request: 8046
-author:
diff --git a/changelogs/unreleased/24915_merge_slash_command.yml b/changelogs/unreleased/24915_merge_slash_command.yml
deleted file mode 100644
index eb8ced8ab01..00000000000
--- a/changelogs/unreleased/24915_merge_slash_command.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Support slash comand `/merge` for merging merge requests.
-merge_request: 7746
-author: Jarka Kadlecova
diff --git a/changelogs/unreleased/25277-milestone-counter-number-with-delimiter.yml b/changelogs/unreleased/25277-milestone-counter-number-with-delimiter.yml
deleted file mode 100644
index 0c9853de3b6..00000000000
--- a/changelogs/unreleased/25277-milestone-counter-number-with-delimiter.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Added number_with_delimiter to counter on milestone panels
-merge_request:
-author: Ryan Harris
diff --git a/changelogs/unreleased/25371-environments-date-created-column-is-not-labeled.yml b/changelogs/unreleased/25371-environments-date-created-column-is-not-labeled.yml
deleted file mode 100644
index 13d3476fe39..00000000000
--- a/changelogs/unreleased/25371-environments-date-created-column-is-not-labeled.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Adds label to Environments "Date Created"
-merge_request: 8376
-author: Saad Shahd
diff --git a/changelogs/unreleased/25430-make-colors-in-runner-status-more-colorblind-friendly.yml b/changelogs/unreleased/25430-make-colors-in-runner-status-more-colorblind-friendly.yml
deleted file mode 100644
index e60c42cdfba..00000000000
--- a/changelogs/unreleased/25430-make-colors-in-runner-status-more-colorblind-friendly.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Change status colors of runners to better defaults
-merge_request:
-author:
diff --git a/changelogs/unreleased/25507-handle-errors-environment-list.yml b/changelogs/unreleased/25507-handle-errors-environment-list.yml
deleted file mode 100644
index 4e9794f7917..00000000000
--- a/changelogs/unreleased/25507-handle-errors-environment-list.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Handle HTTP errors in environment list
-merge_request:
-author:
diff --git a/changelogs/unreleased/25580-trucate-dropdown-for-long-branch.yml b/changelogs/unreleased/25580-trucate-dropdown-for-long-branch.yml
deleted file mode 100644
index 18d3ac050ae..00000000000
--- a/changelogs/unreleased/25580-trucate-dropdown-for-long-branch.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Resolves overflow in compare branch and tags dropdown
-merge_request: 8118
-author:
diff --git a/changelogs/unreleased/25678-remove-user-build.yml b/changelogs/unreleased/25678-remove-user-build.yml
deleted file mode 100644
index 873e637d670..00000000000
--- a/changelogs/unreleased/25678-remove-user-build.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: remove build_user
-merge_request: 8162
-author: Arsenev Vladislav
diff --git a/changelogs/unreleased/25701-standardize-text-colors.yml b/changelogs/unreleased/25701-standardize-text-colors.yml
deleted file mode 100644
index a48ca6c187d..00000000000
--- a/changelogs/unreleased/25701-standardize-text-colors.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: 25701 standardize text colors
-merge_request:
-author:
diff --git a/changelogs/unreleased/25705-your-commands-have-been-executed-is-overkill.yml b/changelogs/unreleased/25705-your-commands-have-been-executed-is-overkill.yml
deleted file mode 100644
index 850e98518a6..00000000000
--- a/changelogs/unreleased/25705-your-commands-have-been-executed-is-overkill.yml
+++ /dev/null
@@ -1,3 +0,0 @@
----
-title: Replace wording for slash command confirmation message
-merge_request: 8123
diff --git a/changelogs/unreleased/25725-remove-window-object.yml b/changelogs/unreleased/25725-remove-window-object.yml
deleted file mode 100644
index c64b71ddd33..00000000000
--- a/changelogs/unreleased/25725-remove-window-object.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Removes unneeded `window` declaration in environments related code
-merge_request: 8456
-author:
diff --git a/changelogs/unreleased/25776-alerts-should-be-responsive.yml b/changelogs/unreleased/25776-alerts-should-be-responsive.yml
deleted file mode 100644
index 15006523d3e..00000000000
--- a/changelogs/unreleased/25776-alerts-should-be-responsive.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Changed alerts to be responsive, centered text on smaller viewports
-merge_request: 8424
-author: Connor Smallman
diff --git a/changelogs/unreleased/25829-update-username-button-remains-disabled-upon-failure.yml b/changelogs/unreleased/25829-update-username-button-remains-disabled-upon-failure.yml
deleted file mode 100644
index c82bacd8bcd..00000000000
--- a/changelogs/unreleased/25829-update-username-button-remains-disabled-upon-failure.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: re-enable change username button after failure
-merge_request: 8332
-author:
diff --git a/changelogs/unreleased/25898-ci-icon-color-mr.yml b/changelogs/unreleased/25898-ci-icon-color-mr.yml
deleted file mode 100644
index dd0f93e176f..00000000000
--- a/changelogs/unreleased/25898-ci-icon-color-mr.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Adds CSS class to status icon on MR widget to prevent non-colored icon
-merge_request: 8219
-author:
diff --git a/changelogs/unreleased/25941-odd-overflow-behavior-for-long-issue-headers.yml b/changelogs/unreleased/25941-odd-overflow-behavior-for-long-issue-headers.yml
deleted file mode 100644
index c28cf7a0f86..00000000000
--- a/changelogs/unreleased/25941-odd-overflow-behavior-for-long-issue-headers.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Change earlier to task_status_short to avoid titlebar line wraps
-merge_request:
-author:
diff --git a/changelogs/unreleased/25946-manual-pipeline-dropdown-casing.yml b/changelogs/unreleased/25946-manual-pipeline-dropdown-casing.yml
deleted file mode 100644
index b753c823348..00000000000
--- a/changelogs/unreleased/25946-manual-pipeline-dropdown-casing.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Use original casing for build action text
-merge_request: 8387
-author:
diff --git a/changelogs/unreleased/25985-combine-members-and-groups-settings-pages.yml b/changelogs/unreleased/25985-combine-members-and-groups-settings-pages.yml
deleted file mode 100644
index 206be8fe3cb..00000000000
--- a/changelogs/unreleased/25985-combine-members-and-groups-settings-pages.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Combined the settings options project members and groups into a single one
- called members
-merge_request:
-author:
diff --git a/changelogs/unreleased/25996-Move-award-emoji-out-of-the-discussion-tab-for-MR.yml b/changelogs/unreleased/25996-Move-award-emoji-out-of-the-discussion-tab-for-MR.yml
deleted file mode 100644
index e05e2dd6fed..00000000000
--- a/changelogs/unreleased/25996-Move-award-emoji-out-of-the-discussion-tab-for-MR.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Move award emoji's out of the discussion tab for merge requests
-merge_request:
-author:
diff --git a/changelogs/unreleased/26014-fix-update-doc.yml b/changelogs/unreleased/26014-fix-update-doc.yml
deleted file mode 100644
index 419c032cb0f..00000000000
--- a/changelogs/unreleased/26014-fix-update-doc.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Re-order update steps in the 8.14 -> 8.15 upgrade guide
-merge_request:
-author:
diff --git a/changelogs/unreleased/26051-fix-missing-endpoint-route-method.yml b/changelogs/unreleased/26051-fix-missing-endpoint-route-method.yml
deleted file mode 100644
index 85440eb86f9..00000000000
--- a/changelogs/unreleased/26051-fix-missing-endpoint-route-method.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Don't instrument 405 Grape calls
-merge_request: 8445
-author:
diff --git a/changelogs/unreleased/26109-preserve-scroll-position-on-autoreload.yml b/changelogs/unreleased/26109-preserve-scroll-position-on-autoreload.yml
deleted file mode 100644
index cde0d114d7c..00000000000
--- a/changelogs/unreleased/26109-preserve-scroll-position-on-autoreload.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Scroll to bottom on build completion if autoscroll was active
-merge_request: 8391
-author:
diff --git a/changelogs/unreleased/26129-add-link-to-branches-page.yml b/changelogs/unreleased/26129-add-link-to-branches-page.yml
deleted file mode 100644
index aceb92dbb9c..00000000000
--- a/changelogs/unreleased/26129-add-link-to-branches-page.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Convert project setting text into protected branch path link
-merge_request: 8377
-author: Ken Ding
diff --git a/changelogs/unreleased/26134-ctrl-enter-does-not-submit-a-new-merge-request.yml b/changelogs/unreleased/26134-ctrl-enter-does-not-submit-a-new-merge-request.yml
deleted file mode 100644
index 40183f8d3fa..00000000000
--- a/changelogs/unreleased/26134-ctrl-enter-does-not-submit-a-new-merge-request.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Make CTRL+Enter submits a new merge request
-merge_request: 8360
-author: Saad Shahd
diff --git a/changelogs/unreleased/26155-merge-request-tabs-don-t-render-when-no-commits-available.yml b/changelogs/unreleased/26155-merge-request-tabs-don-t-render-when-no-commits-available.yml
deleted file mode 100644
index 242a77b5d48..00000000000
--- a/changelogs/unreleased/26155-merge-request-tabs-don-t-render-when-no-commits-available.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: display merge request discussion tab for empty branches
-merge_request: 8347
-author:
diff --git a/changelogs/unreleased/26192-fixes-too-short-input.yml b/changelogs/unreleased/26192-fixes-too-short-input.yml
deleted file mode 100644
index ff707f4694d..00000000000
--- a/changelogs/unreleased/26192-fixes-too-short-input.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fixes too short input for placeholder message in commit listing page
-merge_request: 8367
-author:
diff --git a/changelogs/unreleased/26207-add-hover-animations.yml b/changelogs/unreleased/26207-add-hover-animations.yml
deleted file mode 100644
index 12a69d04717..00000000000
--- a/changelogs/unreleased/26207-add-hover-animations.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add various hover animations throughout the application
-merge_request:
-author:
diff --git a/changelogs/unreleased/26226-generate-all-haml-fixtures-within-teaspoon-fixtures-task.yml b/changelogs/unreleased/26226-generate-all-haml-fixtures-within-teaspoon-fixtures-task.yml
deleted file mode 100644
index 28981291132..00000000000
--- a/changelogs/unreleased/26226-generate-all-haml-fixtures-within-teaspoon-fixtures-task.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Precompile all JavaScript fixtures
-merge_request: 8384
-author:
diff --git a/changelogs/unreleased/26238-buttons-not-accessible.yml b/changelogs/unreleased/26238-buttons-not-accessible.yml
deleted file mode 100644
index 34d38d45709..00000000000
--- a/changelogs/unreleased/26238-buttons-not-accessible.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fixes buttons not being accessible via the keyboard when creating new group
-merge_request: 8469
-author:
diff --git a/changelogs/unreleased/26261-post-api-v3-projects-idorproject-commits-commits-does-not-work-with-project-path.yml b/changelogs/unreleased/26261-post-api-v3-projects-idorproject-commits-commits-does-not-work-with-project-path.yml
deleted file mode 100644
index 37bd7e46b49..00000000000
--- a/changelogs/unreleased/26261-post-api-v3-projects-idorproject-commits-commits-does-not-work-with-project-path.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix Commits API to accept a Project path upon POST
-merge_request:
-author:
diff --git a/changelogs/unreleased/26352-user-dropdown-settings.yml b/changelogs/unreleased/26352-user-dropdown-settings.yml
deleted file mode 100644
index 19bd47b8673..00000000000
--- a/changelogs/unreleased/26352-user-dropdown-settings.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: 26352 Change Profile settings to User / Settings
-merge_request:
-author:
diff --git a/changelogs/unreleased/26435-show-project-avatars-on-mobile.yml b/changelogs/unreleased/26435-show-project-avatars-on-mobile.yml
deleted file mode 100644
index 43afdf45013..00000000000
--- a/changelogs/unreleased/26435-show-project-avatars-on-mobile.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Display project avatars on Admin Area and Projects pages for mobile views
-merge_request:
-author: Ryan Harris
diff --git a/changelogs/unreleased/26445-make-icon-buttons-accessible-via-keyboard.yml b/changelogs/unreleased/26445-make-icon-buttons-accessible-via-keyboard.yml
deleted file mode 100644
index b4aef8fe3da..00000000000
--- a/changelogs/unreleased/26445-make-icon-buttons-accessible-via-keyboard.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Make play button on Pipelines page accessible via keyboard
-merge_request:
-author: Ryan Harris
diff --git a/changelogs/unreleased/26446-access-download-artifacts-via-keyboard.yml b/changelogs/unreleased/26446-access-download-artifacts-via-keyboard.yml
deleted file mode 100644
index 83f6233dd88..00000000000
--- a/changelogs/unreleased/26446-access-download-artifacts-via-keyboard.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Made download artifacts button accessible via keyboard by changing it from
- an anchor tag to an actual button
-merge_request:
-author: Ryan Harris
diff --git a/changelogs/unreleased/26472-math-margin.yml b/changelogs/unreleased/26472-math-margin.yml
deleted file mode 100644
index 3999f521558..00000000000
--- a/changelogs/unreleased/26472-math-margin.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add margin to markdown math blocks
-merge_request:
-author:
diff --git a/changelogs/unreleased/26504-mr-discussion-btn.yml b/changelogs/unreleased/26504-mr-discussion-btn.yml
deleted file mode 100644
index dec74ec61b1..00000000000
--- a/changelogs/unreleased/26504-mr-discussion-btn.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: 26504 Fix styling of MR jump to discussion button
-merge_request:
-author:
diff --git a/changelogs/unreleased/26587-metrics-middleware-endpoint-is-nil.yml b/changelogs/unreleased/26587-metrics-middleware-endpoint-is-nil.yml
deleted file mode 100644
index 5891a5ef6e8..00000000000
--- a/changelogs/unreleased/26587-metrics-middleware-endpoint-is-nil.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Check for env[Grape::Env::GRAPE_ROUTING_ARGS] instead of endpoint.route
-merge_request: 8544
-author:
diff --git a/changelogs/unreleased/26601-dropdown-makes-request-close.yml b/changelogs/unreleased/26601-dropdown-makes-request-close.yml
deleted file mode 100644
index a810e04376d..00000000000
--- a/changelogs/unreleased/26601-dropdown-makes-request-close.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fixes builds dropdown making request when clicked to be closed
-merge_request: 8545
-author:
diff --git a/changelogs/unreleased/26615-pipeline-status-cell.yml b/changelogs/unreleased/26615-pipeline-status-cell.yml
deleted file mode 100644
index 9a19b041e63..00000000000
--- a/changelogs/unreleased/26615-pipeline-status-cell.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fixes pipeline status cell is too wide by adding missing classes in table head cells
-merge_request: 8549
-author:
diff --git a/changelogs/unreleased/26616-fix-search-group-project-filters.yml b/changelogs/unreleased/26616-fix-search-group-project-filters.yml
deleted file mode 100644
index 0fd0dbbfc24..00000000000
--- a/changelogs/unreleased/26616-fix-search-group-project-filters.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix search group/project filtering to show results
-merge_request:
-author:
diff --git a/changelogs/unreleased/26667-pipeline-width-for-huge-pipeline.yml b/changelogs/unreleased/26667-pipeline-width-for-huge-pipeline.yml
deleted file mode 100644
index 08dcc5c3e8c..00000000000
--- a/changelogs/unreleased/26667-pipeline-width-for-huge-pipeline.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fixes big pipeline and small pipeline width problems and tooltips text being outside the tooltip
-merge_request: 8593
-author:
diff --git a/changelogs/unreleased/26773-fix-project-statistics-repository-size.yml b/changelogs/unreleased/26773-fix-project-statistics-repository-size.yml
deleted file mode 100644
index 8ce9bbcb3a9..00000000000
--- a/changelogs/unreleased/26773-fix-project-statistics-repository-size.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Adjust ProjectStatistic#repository_size with values saved as MB
-merge_request: 8616
-author:
diff --git a/changelogs/unreleased/26785-fix-droplab-in-ie-11-v1.yml b/changelogs/unreleased/26785-fix-droplab-in-ie-11-v1.yml
new file mode 100644
index 00000000000..76e9b19b828
--- /dev/null
+++ b/changelogs/unreleased/26785-fix-droplab-in-ie-11-v1.yml
@@ -0,0 +1,4 @@
+---
+title: Add some basic fixes for IE11/Edge
+merge_request:
+author:
diff --git a/changelogs/unreleased/7898-fixes-issue-boards-list-colored-top-border-visual-glitch.yml b/changelogs/unreleased/7898-fixes-issue-boards-list-colored-top-border-visual-glitch.yml
deleted file mode 100644
index 74412c32375..00000000000
--- a/changelogs/unreleased/7898-fixes-issue-boards-list-colored-top-border-visual-glitch.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fixes issue boards list colored top border visual glitch
-merge_request: 7898
-author: Pier Paolo Ramon
diff --git a/changelogs/unreleased/8623-correct-robots-txt.yml b/changelogs/unreleased/8623-correct-robots-txt.yml
deleted file mode 100644
index 00ed80511cc..00000000000
--- a/changelogs/unreleased/8623-correct-robots-txt.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: "Correct User-agent placement in robots.txt"
-merge_request: 8623
-author: Eric Sabelhaus
diff --git a/changelogs/unreleased/add-changelog-search-bar-first-iteration.yml b/changelogs/unreleased/add-changelog-search-bar-first-iteration.yml
deleted file mode 100644
index 4d83d744be7..00000000000
--- a/changelogs/unreleased/add-changelog-search-bar-first-iteration.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Search bar redesign first iteration
-merge_request: 7345
-author:
diff --git a/changelogs/unreleased/add_email_password_confirmation.yml b/changelogs/unreleased/add_email_password_confirmation.yml
deleted file mode 100644
index 92f9b9b7a6d..00000000000
--- a/changelogs/unreleased/add_email_password_confirmation.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add email confirmation field to registration form
-merge_request: 7432
-author:
diff --git a/changelogs/unreleased/additional-award-emoji-repositioning-fixes.yml b/changelogs/unreleased/additional-award-emoji-repositioning-fixes.yml
deleted file mode 100644
index 8d5a94c3aa8..00000000000
--- a/changelogs/unreleased/additional-award-emoji-repositioning-fixes.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Removed bottom padding from merge manually from CLI because of repositioning award emoji's
-merge_request:
-author:
diff --git a/changelogs/unreleased/allow_plus_sign_for_snippets.yml b/changelogs/unreleased/allow_plus_sign_for_snippets.yml
deleted file mode 100644
index 62d9dd74d07..00000000000
--- a/changelogs/unreleased/allow_plus_sign_for_snippets.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow to use + symbol in filenames
-merge_request: 6644
-author: blackst0ne
diff --git a/changelogs/unreleased/asciidoctor-plantuml.yml b/changelogs/unreleased/asciidoctor-plantuml.yml
deleted file mode 100644
index ba6ef7c0800..00000000000
--- a/changelogs/unreleased/asciidoctor-plantuml.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add support for PlantUML diagrams in AsciiDoc documents.
-merge_request: 7810
-author: Horacio Sanson
diff --git a/changelogs/unreleased/badge-color-on-white-bg.yml b/changelogs/unreleased/badge-color-on-white-bg.yml
deleted file mode 100644
index 680d7ff11f0..00000000000
--- a/changelogs/unreleased/badge-color-on-white-bg.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Added lighter count badge background-color for on white backgrounds
-merge_request: 7873
-author:
diff --git a/changelogs/unreleased/bug-project-feature-compatibility.yml b/changelogs/unreleased/bug-project-feature-compatibility.yml
deleted file mode 100644
index 2124ee085e0..00000000000
--- a/changelogs/unreleased/bug-project-feature-compatibility.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Mutate the attribute instead of issuing a write operation to the DB in `ProjectFeaturesCompatibility`
- concern.
-merge_request: 8552
-author:
diff --git a/changelogs/unreleased/clipboard-button-text.yml b/changelogs/unreleased/clipboard-button-text.yml
deleted file mode 100644
index dc93da60426..00000000000
--- a/changelogs/unreleased/clipboard-button-text.yml
+++ /dev/null
@@ -1,3 +0,0 @@
----
-title: 'Copy <some text> to clipboard'
-merge_request: 8535
diff --git a/changelogs/unreleased/didemacet-ci-lint-page.yml b/changelogs/unreleased/didemacet-ci-lint-page.yml
deleted file mode 100644
index 07386321c9d..00000000000
--- a/changelogs/unreleased/didemacet-ci-lint-page.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Change CI template linter textarea with Ace Editor
-merge_request: 8452
-author: Didem Acet
diff --git a/changelogs/unreleased/dot-in-project-queries.yml b/changelogs/unreleased/dot-in-project-queries.yml
deleted file mode 100644
index fc48dc7b74d..00000000000
--- a/changelogs/unreleased/dot-in-project-queries.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow API query to find projects with dots in their name
-merge_request:
-author: Bruno Melli
diff --git a/changelogs/unreleased/dz-nested-group-misc.yml b/changelogs/unreleased/dz-nested-group-misc.yml
deleted file mode 100644
index 9c9d0b1c644..00000000000
--- a/changelogs/unreleased/dz-nested-group-misc.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Show nested groups tab on group page
-merge_request: 8308
-author:
diff --git a/changelogs/unreleased/dz-rename-invalid-users.yml b/changelogs/unreleased/dz-rename-invalid-users.yml
deleted file mode 100644
index f420b069531..00000000000
--- a/changelogs/unreleased/dz-rename-invalid-users.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Rename users with namespace ending with .git
-merge_request: 8309
-author:
diff --git a/changelogs/unreleased/env-var-in-redis-config.yml b/changelogs/unreleased/env-var-in-redis-config.yml
deleted file mode 100644
index 561ea7f514e..00000000000
--- a/changelogs/unreleased/env-var-in-redis-config.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow to use ENV variables in redis config
-merge_request: 8073
-author: Semyon Pupkov
diff --git a/changelogs/unreleased/feature-1376-allow-write-access-deploy-keys.yml b/changelogs/unreleased/feature-1376-allow-write-access-deploy-keys.yml
deleted file mode 100644
index 0fd590a877b..00000000000
--- a/changelogs/unreleased/feature-1376-allow-write-access-deploy-keys.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow to add deploy keys with write-access
-merge_request: 5807
-author: Ali Ibrahim
diff --git a/changelogs/unreleased/feature-admin-merge-groups-and-projects.yml b/changelogs/unreleased/feature-admin-merge-groups-and-projects.yml
deleted file mode 100644
index 0c0b74b686a..00000000000
--- a/changelogs/unreleased/feature-admin-merge-groups-and-projects.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Merged the 'Groups' and 'Projects' tabs when viewing user profiles
-merge_request: 8323
-author: James Gregory
diff --git a/changelogs/unreleased/feature-gitaly-feature-flag.yml b/changelogs/unreleased/feature-gitaly-feature-flag.yml
deleted file mode 100644
index 1fa566aeb10..00000000000
--- a/changelogs/unreleased/feature-gitaly-feature-flag.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Pass Gitaly resource path to gitlab-workhorse if Gitaly is enabled
-merge_request: 8440
-author:
diff --git a/changelogs/unreleased/feature-log-ldap-to-application-log.yml b/changelogs/unreleased/feature-log-ldap-to-application-log.yml
deleted file mode 100644
index 4cfbc23edb7..00000000000
--- a/changelogs/unreleased/feature-log-ldap-to-application-log.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Log LDAP blocking/unblocking events to application log
-merge_request: 8042
-author: Markus Koller
diff --git a/changelogs/unreleased/feature-more-storage-statistics.yml b/changelogs/unreleased/feature-more-storage-statistics.yml
deleted file mode 100644
index 824fd36dc34..00000000000
--- a/changelogs/unreleased/feature-more-storage-statistics.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add more storage statistics
-merge_request: 7754
-author: Markus Koller
diff --git a/changelogs/unreleased/filename-to-file-path.yml b/changelogs/unreleased/filename-to-file-path.yml
deleted file mode 100644
index 3c6c838595a..00000000000
--- a/changelogs/unreleased/filename-to-file-path.yml
+++ /dev/null
@@ -1,3 +0,0 @@
----
-title: Rename filename to file path in tooltip of file header in merge request diff
-merge_request: 8314 \ No newline at end of file
diff --git a/changelogs/unreleased/fill-authorized-projects.yml b/changelogs/unreleased/fill-authorized-projects.yml
deleted file mode 100644
index e8e33011a15..00000000000
--- a/changelogs/unreleased/fill-authorized-projects.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fill missing authorized projects rows
-merge_request:
-author:
diff --git a/changelogs/unreleased/fix-api-deprecation.yml b/changelogs/unreleased/fix-api-deprecation.yml
deleted file mode 100644
index 90285ddf058..00000000000
--- a/changelogs/unreleased/fix-api-deprecation.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix a Grape deprecation, use `#request_method` instead of `#route_method`
-merge_request:
-author:
diff --git a/changelogs/unreleased/fix-blame-500.yml b/changelogs/unreleased/fix-blame-500.yml
deleted file mode 100644
index 379d81aaa44..00000000000
--- a/changelogs/unreleased/fix-blame-500.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix blame 500 error on invalid path.
-merge_request: 25761
-author: Jeff Stubler
diff --git a/changelogs/unreleased/fix-boards-search-typo.yml b/changelogs/unreleased/fix-boards-search-typo.yml
deleted file mode 100644
index 0c083fc0d10..00000000000
--- a/changelogs/unreleased/fix-boards-search-typo.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: 'Fix typo: seach to search'
-merge_request: 8370
-author:
diff --git a/changelogs/unreleased/fix-broken-url-on-group-avatar.yml b/changelogs/unreleased/fix-broken-url-on-group-avatar.yml
deleted file mode 100644
index 7ce22b4826e..00000000000
--- a/changelogs/unreleased/fix-broken-url-on-group-avatar.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix broken url on group avatar
-merge_request: 8464
-author: hogewest
diff --git a/changelogs/unreleased/fix-build-sort-order.yml b/changelogs/unreleased/fix-build-sort-order.yml
deleted file mode 100644
index a6d6371f69a..00000000000
--- a/changelogs/unreleased/fix-build-sort-order.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Sort numbers in build names more intelligently
-merge_request: 8277
-author:
diff --git a/changelogs/unreleased/fix-copy-issues-empty-state.yml b/changelogs/unreleased/fix-copy-issues-empty-state.yml
deleted file mode 100644
index a87b7612217..00000000000
--- a/changelogs/unreleased/fix-copy-issues-empty-state.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Improve copy in Issue Tracker empty state
-merge_request: 8202
-author:
diff --git a/changelogs/unreleased/fix-external-status-badge-links.yml b/changelogs/unreleased/fix-external-status-badge-links.yml
deleted file mode 100644
index 2287a9b76c4..00000000000
--- a/changelogs/unreleased/fix-external-status-badge-links.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Link external build badge to its target URL
-merge_request: 8611
-author:
diff --git a/changelogs/unreleased/fix-keep-artifacts-button-visibility.yml b/changelogs/unreleased/fix-keep-artifacts-button-visibility.yml
deleted file mode 100644
index 3d8cf1c74a2..00000000000
--- a/changelogs/unreleased/fix-keep-artifacts-button-visibility.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Hide build artifacts keep button if operation is not allowed
-merge_request: 8501
-author:
diff --git a/changelogs/unreleased/fix-light-hr-in-descriptions.yml b/changelogs/unreleased/fix-light-hr-in-descriptions.yml
deleted file mode 100644
index 8efd471e416..00000000000
--- a/changelogs/unreleased/fix-light-hr-in-descriptions.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Darkened hr border color in descriptions because of update of bootstrap
-merge_request: 8333
-author:
diff --git a/changelogs/unreleased/fix-more-orphans-remove-undeleted-groups.yml b/changelogs/unreleased/fix-more-orphans-remove-undeleted-groups.yml
deleted file mode 100644
index bc2068b8177..00000000000
--- a/changelogs/unreleased/fix-more-orphans-remove-undeleted-groups.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove extra orphaned rows when removing stray namespaces
-merge_request: 7841
-author:
diff --git a/changelogs/unreleased/fix-no-milestone-option-for-projects-endpoint-23194.yml b/changelogs/unreleased/fix-no-milestone-option-for-projects-endpoint-23194.yml
deleted file mode 100644
index 98066537723..00000000000
--- a/changelogs/unreleased/fix-no-milestone-option-for-projects-endpoint-23194.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: 'API: fix query response for `/projects/:id/issues?milestone="No%20Milestone"`'
-merge_request: 8457
-author: Panagiotis Atmatzidis, David Eisner
diff --git a/changelogs/unreleased/fix-project-delete-tooltip.yml b/changelogs/unreleased/fix-project-delete-tooltip.yml
deleted file mode 100644
index 42fd9c32519..00000000000
--- a/changelogs/unreleased/fix-project-delete-tooltip.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix project queued for deletion re-creation tooltip
-merge_request:
-author:
diff --git a/changelogs/unreleased/fix-serialized-commit-path.yml b/changelogs/unreleased/fix-serialized-commit-path.yml
deleted file mode 100644
index 4e4df503874..00000000000
--- a/changelogs/unreleased/fix-serialized-commit-path.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix links to commits pages on pipelines list page
-merge_request: 8558
-author:
diff --git a/changelogs/unreleased/fix-timezone-due-date-picker.yml b/changelogs/unreleased/fix-timezone-due-date-picker.yml
deleted file mode 100644
index 2e6b71c70ca..00000000000
--- a/changelogs/unreleased/fix-timezone-due-date-picker.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix date inconsistency on due date picker
-merge_request: 7422
-author: Giuliano Varriale
diff --git a/changelogs/unreleased/fix-user-api-confirm-param.yml b/changelogs/unreleased/fix-user-api-confirm-param.yml
deleted file mode 100644
index 42642576634..00000000000
--- a/changelogs/unreleased/fix-user-api-confirm-param.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix 500 error when POSTing to Users API with optional confirm param
-merge_request:
-author:
diff --git a/changelogs/unreleased/get_last_used_date_of_ssh_key.yml b/changelogs/unreleased/get_last_used_date_of_ssh_key.yml
deleted file mode 100644
index b753949922c..00000000000
--- a/changelogs/unreleased/get_last_used_date_of_ssh_key.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Record and show last used date of SSH Keys
-merge_request: 8113
-author: Vincent Wong
diff --git a/changelogs/unreleased/i--25814-500-error.yml b/changelogs/unreleased/i--25814-500-error.yml
deleted file mode 100644
index cd55ede84c8..00000000000
--- a/changelogs/unreleased/i--25814-500-error.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix Compare page throws 500 error when any branch/reference is not selected
-merge_request: 8492
-author: Martin Cabrera
diff --git a/changelogs/unreleased/input-button-hover.yml b/changelogs/unreleased/input-button-hover.yml
deleted file mode 100644
index cbb35adb769..00000000000
--- a/changelogs/unreleased/input-button-hover.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add hover state to MR comment reply button
-merge_request:
-author:
diff --git a/changelogs/unreleased/issue-boards-animate.yml b/changelogs/unreleased/issue-boards-animate.yml
deleted file mode 100644
index 28394aec3d5..00000000000
--- a/changelogs/unreleased/issue-boards-animate.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Added animations to issue boards interactions
-merge_request:
-author:
diff --git a/changelogs/unreleased/issue_22664.yml b/changelogs/unreleased/issue_22664.yml
deleted file mode 100644
index 18a8d9ec6be..00000000000
--- a/changelogs/unreleased/issue_22664.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Check if user can read project before being assigned to issue
-merge_request:
-author:
diff --git a/changelogs/unreleased/issue_25017.yml b/changelogs/unreleased/issue_25017.yml
deleted file mode 100644
index 09126ae81bc..00000000000
--- a/changelogs/unreleased/issue_25017.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Show 'too many changes' message for created merge requests when they are too large
-merge_request:
-author:
diff --git a/changelogs/unreleased/issue_25578.yml b/changelogs/unreleased/issue_25578.yml
deleted file mode 100644
index e10f1d232af..00000000000
--- a/changelogs/unreleased/issue_25578.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix redirect after update file when user has forked project
-merge_request:
-author:
diff --git a/changelogs/unreleased/issue_25682.yml b/changelogs/unreleased/issue_25682.yml
deleted file mode 100644
index a50138756ba..00000000000
--- a/changelogs/unreleased/issue_25682.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Parse JIRA issue references even if Issue Tracker is disabled
-merge_request:
-author:
diff --git a/changelogs/unreleased/issues-8081.yml b/changelogs/unreleased/issues-8081.yml
deleted file mode 100644
index 82f746937bc..00000000000
--- a/changelogs/unreleased/issues-8081.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: change 'gray' color theme name to 'black' to match the actual color
-merge_request: 7908
-author: BM5k
diff --git a/changelogs/unreleased/ldap_maint_task.yml b/changelogs/unreleased/ldap_maint_task.yml
deleted file mode 100644
index 8acffba0ce5..00000000000
--- a/changelogs/unreleased/ldap_maint_task.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add LDAP Rake task to rename a provider
-merge_request: 2181
-author:
diff --git a/changelogs/unreleased/login-page-font-size.yml b/changelogs/unreleased/login-page-font-size.yml
deleted file mode 100644
index e7775006673..00000000000
--- a/changelogs/unreleased/login-page-font-size.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Decreases font-size on login page
-merge_request:
-author:
diff --git a/changelogs/unreleased/markdown-area-height-fix.yml b/changelogs/unreleased/markdown-area-height-fix.yml
deleted file mode 100644
index bf1b82cfd12..00000000000
--- a/changelogs/unreleased/markdown-area-height-fix.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Autoresize markdown preview
-merge_request: 8607
-author: Didem Acet
diff --git a/changelogs/unreleased/merge-dropdown-this-context.yml b/changelogs/unreleased/merge-dropdown-this-context.yml
new file mode 100644
index 00000000000..5c4890fcaa2
--- /dev/null
+++ b/changelogs/unreleased/merge-dropdown-this-context.yml
@@ -0,0 +1,4 @@
+---
+title: Fixed bug where links in merge dropdown wouldn't work
+merge_request:
+author:
diff --git a/changelogs/unreleased/mr-tabs-alignment-sidebar-open.yml b/changelogs/unreleased/mr-tabs-alignment-sidebar-open.yml
deleted file mode 100644
index b8c7b78cf0d..00000000000
--- a/changelogs/unreleased/mr-tabs-alignment-sidebar-open.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fixed merge request tabs dont move when opening collapsed sidebar
-merge_request:
-author:
diff --git a/changelogs/unreleased/nuke-ugly-spaces-in-changelog-generator.yml b/changelogs/unreleased/nuke-ugly-spaces-in-changelog-generator.yml
deleted file mode 100644
index fd173031107..00000000000
--- a/changelogs/unreleased/nuke-ugly-spaces-in-changelog-generator.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove trailing whitespace when generating changelog entry
-merge_request: 7948
-author:
diff --git a/changelogs/unreleased/pc-add-gitaly-to-architecture.yml b/changelogs/unreleased/pc-add-gitaly-to-architecture.yml
deleted file mode 100644
index 7c18da698df..00000000000
--- a/changelogs/unreleased/pc-add-gitaly-to-architecture.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add Gitaly to the architecture documentation
-merge_request: 8264
-author: Pablo Carranza <pablo@gitlab.com>
diff --git a/changelogs/unreleased/pipelines-graph-html-css.yml b/changelogs/unreleased/pipelines-graph-html-css.yml
deleted file mode 100644
index ff0c3122fdb..00000000000
--- a/changelogs/unreleased/pipelines-graph-html-css.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fixes and Improves CSS and HTML problems in mini pipeline graph and builds dropdown
-merge_request: 8443
-author:
diff --git a/changelogs/unreleased/pmq20-gitlab-ce-psvr-head-cache.yml b/changelogs/unreleased/pmq20-gitlab-ce-psvr-head-cache.yml
deleted file mode 100644
index 23230128dc9..00000000000
--- a/changelogs/unreleased/pmq20-gitlab-ce-psvr-head-cache.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Expire related caches after changing HEAD
-merge_request:
-author: Minqi Pan
diff --git a/changelogs/unreleased/re-style-issue-new-branch.yml b/changelogs/unreleased/re-style-issue-new-branch.yml
deleted file mode 100644
index 977a54ff2ae..00000000000
--- a/changelogs/unreleased/re-style-issue-new-branch.yml
+++ /dev/null
@@ -1,3 +0,0 @@
----
-title: Remove checking branches state in issue new branch button
-merge_request: 8023
diff --git a/changelogs/unreleased/recaptcha_500.yml b/changelogs/unreleased/recaptcha_500.yml
deleted file mode 100644
index de9ef183d5e..00000000000
--- a/changelogs/unreleased/recaptcha_500.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Properly handle failed reCAPTCHA on user registration
-merge_request: 8403
-author:
diff --git a/changelogs/unreleased/reduce-queries-milestone-index.yml b/changelogs/unreleased/reduce-queries-milestone-index.yml
deleted file mode 100644
index a779b58c973..00000000000
--- a/changelogs/unreleased/reduce-queries-milestone-index.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Use cached values to compute total issues count in milestone index pages
-merge_request: 8518
-author:
diff --git a/changelogs/unreleased/refresh-authorizations-tighter-lease.yml b/changelogs/unreleased/refresh-authorizations-tighter-lease.yml
deleted file mode 100644
index ab42b2eb72d..00000000000
--- a/changelogs/unreleased/refresh-authorizations-tighter-lease.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Synchronize all project authorization refreshing work to prevent race conditions
-merge_request:
-author:
diff --git a/changelogs/unreleased/remove-project-authorizations-id-column.yml b/changelogs/unreleased/remove-project-authorizations-id-column.yml
deleted file mode 100644
index 24c86f0fb1b..00000000000
--- a/changelogs/unreleased/remove-project-authorizations-id-column.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove the project_authorizations.id column
-merge_request:
-author:
diff --git a/changelogs/unreleased/remove-successful-pipeline-emails-for-now.yml b/changelogs/unreleased/remove-successful-pipeline-emails-for-now.yml
deleted file mode 100644
index 47d484e5c84..00000000000
--- a/changelogs/unreleased/remove-successful-pipeline-emails-for-now.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Make successful pipeline emails off for watchers
-merge_request: 8176
-author:
diff --git a/changelogs/unreleased/restore-backup-when-env-variable-is-passed.yml b/changelogs/unreleased/restore-backup-when-env-variable-is-passed.yml
deleted file mode 100644
index 8ec3cfdbb08..00000000000
--- a/changelogs/unreleased/restore-backup-when-env-variable-is-passed.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Restore backup correctly when "BACKUP" environment variable is passed
-merge_request: 8477
-author:
diff --git a/changelogs/unreleased/sandish-gitlab-ce-update_ret_val.yml b/changelogs/unreleased/sandish-gitlab-ce-update_ret_val.yml
deleted file mode 100644
index 7107ddfd982..00000000000
--- a/changelogs/unreleased/sandish-gitlab-ce-update_ret_val.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Ensure updating project settings shows a flash message on success
-merge_request: 8579
-author: Sandish Chen
diff --git a/changelogs/unreleased/single-edit-comment-widget-2.yml b/changelogs/unreleased/single-edit-comment-widget-2.yml
deleted file mode 100644
index e8b8beb15de..00000000000
--- a/changelogs/unreleased/single-edit-comment-widget-2.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Refactored note edit form to improve frontend performance on MR and Issues
- pages, especially pages with has a lot of discussions in it
-merge_request: 8356
-author:
diff --git a/changelogs/unreleased/speed-up-dashboard-milestone-index.yml b/changelogs/unreleased/speed-up-dashboard-milestone-index.yml
deleted file mode 100644
index ba4ff931ea8..00000000000
--- a/changelogs/unreleased/speed-up-dashboard-milestone-index.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Speed up dashboard milestone index by scoping IssuesFinder to user authorized
- projects
-merge_request: 8524
-author:
diff --git a/changelogs/unreleased/support-google-cloud-storage-backups.yml b/changelogs/unreleased/support-google-cloud-storage-backups.yml
deleted file mode 100644
index cec279a5c73..00000000000
--- a/changelogs/unreleased/support-google-cloud-storage-backups.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Re-add Google Cloud Storage as a backup strategy
-merge_request:
-author:
diff --git a/changelogs/unreleased/time-tracking-api.yml b/changelogs/unreleased/time-tracking-api.yml
deleted file mode 100644
index b58d73bef81..00000000000
--- a/changelogs/unreleased/time-tracking-api.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add new endpoints for Time Tracking.
-merge_request: 8483
-author:
diff --git a/changelogs/unreleased/update-gitlab-markup-gem.yml b/changelogs/unreleased/update-gitlab-markup-gem.yml
deleted file mode 100644
index 96cdfd051f0..00000000000
--- a/changelogs/unreleased/update-gitlab-markup-gem.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Update the gitlab-markup gem to the version 1.5.1
-merge_request: 8509
-author:
diff --git a/changelogs/unreleased/validate-title-length.yml b/changelogs/unreleased/validate-title-length.yml
deleted file mode 100644
index 7abf1c4d05a..00000000000
--- a/changelogs/unreleased/validate-title-length.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: "Validate label's title length"
-merge_request: 5767
-author: Tomáš Kukrál
diff --git a/changelogs/unreleased/view-ce-vs-ee.yml b/changelogs/unreleased/view-ce-vs-ee.yml
deleted file mode 100644
index 38bce4ac7c3..00000000000
--- a/changelogs/unreleased/view-ce-vs-ee.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: About GitLab link in sidebar that links to help page
-merge_request: 8316
-author:
diff --git a/changelogs/unreleased/zj-unadressable-url-variables.yml b/changelogs/unreleased/zj-unadressable-url-variables.yml
deleted file mode 100644
index 6c412bd0540..00000000000
--- a/changelogs/unreleased/zj-unadressable-url-variables.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Don't validate environment urls on .gitlab-ci.yml
-merge_request:
-author:
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 1fc6ed28c74..6620b765e02 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -307,9 +307,9 @@ constraints(ProjectUrlConstrainer.new) do
end
end
end
-
namespace :settings do
resource :members, only: [:show]
+ resource :integrations, only: [:show]
end
# Since both wiki and repository routing contains wildcard characters
diff --git a/db/migrate/20170121123724_add_index_to_ci_builds_for_status_runner_id_and_type.rb b/db/migrate/20170121123724_add_index_to_ci_builds_for_status_runner_id_and_type.rb
new file mode 100644
index 00000000000..4ea953f2b78
--- /dev/null
+++ b/db/migrate/20170121123724_add_index_to_ci_builds_for_status_runner_id_and_type.rb
@@ -0,0 +1,17 @@
+class AddIndexToCiBuildsForStatusRunnerIdAndType < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_builds, [:status, :type, :runner_id]
+ end
+
+ def down
+ if index_exists?(:ci_builds, [:status, :type, :runner_id])
+ remove_index :ci_builds, column: [:status, :type, :runner_id]
+ end
+ end
+end
diff --git a/db/migrate/20170121130655_add_index_to_ci_runners_for_is_shared.rb b/db/migrate/20170121130655_add_index_to_ci_runners_for_is_shared.rb
new file mode 100644
index 00000000000..620befcf4d7
--- /dev/null
+++ b/db/migrate/20170121130655_add_index_to_ci_runners_for_is_shared.rb
@@ -0,0 +1,17 @@
+class AddIndexToCiRunnersForIsShared < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_runners, :is_shared
+ end
+
+ def down
+ if index_exists?(:ci_runners, :is_shared)
+ remove_index :ci_runners, :is_shared
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 7815392c1c3..3c836db27fc 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20170106172224) do
+ActiveRecord::Schema.define(version: 20170121130655) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -224,6 +224,7 @@ ActiveRecord::Schema.define(version: 20170106172224) do
add_index "ci_builds", ["gl_project_id"], name: "index_ci_builds_on_gl_project_id", using: :btree
add_index "ci_builds", ["project_id"], name: "index_ci_builds_on_project_id", using: :btree
add_index "ci_builds", ["runner_id"], name: "index_ci_builds_on_runner_id", using: :btree
+ add_index "ci_builds", ["status", "type", "runner_id"], name: "index_ci_builds_on_status_and_type_and_runner_id", using: :btree
add_index "ci_builds", ["status"], name: "index_ci_builds_on_status", using: :btree
add_index "ci_builds", ["token"], name: "index_ci_builds_on_token", unique: true, using: :btree
@@ -327,6 +328,7 @@ ActiveRecord::Schema.define(version: 20170106172224) do
t.boolean "locked", default: false, null: false
end
+ add_index "ci_runners", ["is_shared"], name: "index_ci_runners_on_is_shared", using: :btree
add_index "ci_runners", ["locked"], name: "index_ci_runners_on_locked", using: :btree
add_index "ci_runners", ["token"], name: "index_ci_runners_on_token", using: :btree
diff --git a/doc/README.md b/doc/README.md
index 43261ef7457..e329131b8ee 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -53,7 +53,8 @@
- [Migrate GitLab CI to CE/EE](migrate_ci_to_ce/README.md) Follow this guide to migrate your existing GitLab CI data to GitLab CE/EE.
- [Git LFS configuration](workflow/lfs/lfs_administration.md)
- [Housekeeping](administration/housekeeping.md) Keep your Git repository tidy and fast.
-- [GitLab Performance Monitoring](administration/monitoring/performance/introduction.md) Configure GitLab and InfluxDB for measuring performance metrics.
+- [GitLab performance monitoring with InfluxDB](administration/monitoring/performance/introduction.md) Configure GitLab and InfluxDB for measuring performance metrics.
+- [GitLab performance monitoring with Prometheus](administration/monitoring/performance/prometheus.md) Configure GitLab and Prometheus for measuring performance metrics.
- [Request Profiling](administration/monitoring/performance/request_profiling.md) Get a detailed profile on slow requests.
- [Monitoring uptime](user/admin_area/monitoring/health_check.md) Check the server status using the health check endpoint.
- [Debugging Tips](administration/troubleshooting/debug.md) Tips to debug problems when things go wrong
diff --git a/doc/administration/monitoring/performance/introduction.md b/doc/administration/monitoring/performance/introduction.md
index 79904916b7e..8b106e89cc2 100644
--- a/doc/administration/monitoring/performance/introduction.md
+++ b/doc/administration/monitoring/performance/introduction.md
@@ -12,6 +12,11 @@ documents in order to understand and properly configure GitLab Performance Monit
- [InfluxDB Schema](influxdb_schema.md)
- [Grafana Install/Configuration](grafana_configuration.md)
+>**Note:**
+Omnibus GitLab 8.16 includes Prometheus as an additional tool to collect
+metrics. It will eventually replace InfluxDB when their metrics collection is
+on par. Read more in the [Prometheus documentation](prometheus.md).
+
## Introduction to GitLab Performance Monitoring
GitLab Performance Monitoring makes it possible to measure a wide variety of statistics
diff --git a/doc/administration/monitoring/performance/prometheus.md b/doc/administration/monitoring/performance/prometheus.md
new file mode 100644
index 00000000000..51c63325064
--- /dev/null
+++ b/doc/administration/monitoring/performance/prometheus.md
@@ -0,0 +1,102 @@
+# GitLab Prometheus
+
+>**Notes:**
+- Prometheus and the node exporter are bundled in the Omnibus GitLab package
+ since GitLab 8.16. For installations from source you will have to install
+ them yourself. Over subsequent releases additional GitLab metrics will be
+ captured.
+- Prometheus services are off by default but will be on starting with GitLab 9.0.
+
+[Prometheus] is a powerful time-series monitoring service, providing a flexible
+platform for monitoring GitLab and other software products.
+GitLab provides out of the box monitoring with Prometheus, providing easy
+access to high quality time-series monitoring of GitLab services.
+
+## Overview
+
+Prometheus works by periodically connecting to data sources and collecting their
+performance metrics. To view and work with the monitoring data, you can either
+connect directly to Prometheus or utilize a dashboard tool like [Grafana].
+
+## Configuring Prometheus
+
+>**Note:**
+Available since Omnibus GitLab 8.16. For installations from source you'll
+have to install and configure it yourself.
+
+To enable Prometheus:
+
+1. Edit `/etc/gitlab/gitlab.rb`
+1. Find and uncomment the following line, making sure it's set to `true`:
+
+ ```ruby
+ prometheus['enable'] = true
+ ```
+
+1. Save the file and [reconfigure GitLab][reconfigure] for the changes to
+ take effect
+
+By default, Prometheus will run as the `gitlab-prometheus` user and listen on
+TCP port `9090` under localhost. If the [node exporter](#node-exporter) service
+has been enabled, it will automatically be set up as a monitoring target for
+Prometheus.
+
+## Viewing Performance Metrics
+
+After you have [enabled Prometheus](#configuring-prometheus), you can visit
+`<your_domain_name>:9090` for the dashboard that Prometheus offers by default.
+
+The performance data collected by Prometheus can be viewed directly in the
+Prometheus console or through a compatible dashboard tool.
+The Prometheus interface provides a [flexible query language][prom-query] to work
+with the collected data where you can visualize their output.
+For a more fully featured dashboard, Grafana can be used and has
+[official support for Prometheus][prom-grafana].
+
+## Prometheus exporters
+
+There are a number of libraries and servers which help in exporting existing
+metrics from third-party systems as Prometheus metrics. This is useful for cases
+where it is not feasible to instrument a given system with Prometheus metrics
+directly (for example, HAProxy or Linux system stats). You can read more in the
+[Prometheus exporters and integrations documentation][prom-exporters].
+
+While you can use any exporter you like with your GitLab installation, the
+following ones documented here are bundled in the Omnibus GitLab packages
+making it easy to configure and use.
+
+### Node exporter
+
+>**Note:**
+Available since Omnibus GitLab 8.16. For installations from source you'll
+have to install and configure it yourself.
+
+The [node exporter] allows you to measure various machine resources such as
+memory, disk and CPU utilization.
+
+To enable the node exporter:
+
+1. [Enable Prometheus](#configuring-prometheus)
+1. Edit `/etc/gitlab/gitlab.rb`
+1. Find and uncomment the following line, making sure it's set to `true`:
+
+ ```ruby
+ node_exporter['enable'] = true
+ ```
+
+1. Save the file and [reconfigure GitLab][reconfigure] for the changes to
+ take effect
+
+Prometheus it will now automatically begin collecting performance data from
+the node exporter. You can visit `<your_domain_name>:9100/metrics` for a real
+time representation of the metrics that are collected. Refresh the page and
+you will see the data change.
+
+[grafana]: https://grafana.net
+[node exporter]: https://github.com/prometheus/node_exporter
+[prometheus]: https://prometheus.io
+[prom-query]: https://prometheus.io/docs/querying/basics
+[prom-grafana]: https://prometheus.io/docs/visualization/grafana/
+[scrape-config]: https://prometheus.io/docs/operating/configuration/#%3Cscrape_config%3E
+[prom-exporters]: https://prometheus.io/docs/instrumenting/exporters/
+[reconfigure]: ../../restart_gitlab.md#omnibus-gitlab-reconfigure
diff --git a/doc/api/README.md b/doc/api/README.md
index f65b934b9db..20f28e8d30e 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -104,6 +104,13 @@ that needs access to the GitLab API.
Once you have your token, pass it to the API using either the `private_token`
parameter or the `PRIVATE-TOKEN` header.
+> [Introduced][ce-5951] in GitLab 8.15.
+
+Personal Access Tokens can be created with one or more scopes that allow various actions
+that a given token can perform. Although there are only two scopes available at the
+moment – `read_user` and `api` – the groundwork has been laid to add more scopes easily.
+
+At any time you can revoke any personal access token by just clicking **Revoke**.
### Session Cookie
@@ -380,3 +387,4 @@ programming languages. Visit the [GitLab website] for a complete list.
[GitLab website]: https://about.gitlab.com/applications/#api-clients "Clients using the GitLab API"
[lib-api-url]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/api/api.rb
[ce-3749]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3749
+[ce-5951]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5951
diff --git a/doc/integration/oauth_provider.md b/doc/integration/oauth_provider.md
index 0c53584d201..af8a1c4e5ed 100644
--- a/doc/integration/oauth_provider.md
+++ b/doc/integration/oauth_provider.md
@@ -74,8 +74,10 @@ in the **Authorized applications** section under **Profile Settings > Applicatio
---
-As you can see, the default scope `api` is used, which is the only scope that
-GitLab supports so far. At any time you can revoke any access by just clicking
-**Revoke**.
+GitLab's OAuth applications support scopes, which allow various actions that any given
+application can perform. Although there are only two scopes available at the
+moment – `read_user` and `api` – the groundwork has been laid to add more scopes easily.
+
+At any time you can revoke any access by just clicking **Revoke**.
[oauth]: http://oauth.net/2/ "OAuth website"
diff --git a/features/project/active_tab.feature b/features/project/active_tab.feature
index 57dda9c2234..d033e6b167b 100644
--- a/features/project/active_tab.feature
+++ b/features/project/active_tab.feature
@@ -39,10 +39,10 @@ Feature: Project Active Tab
# Sub Tabs: Settings
- Scenario: On Project Settings/Hooks
+ Scenario: On Project Settings/Integrations
Given I visit my project's settings page
- And I click the "Hooks" tab
- Then the active sub nav should be Hooks
+ And I click the "Integrations" tab
+ Then the active sub nav should be Integrations
And no other sub navs should be active
And the active main tab should be Settings
diff --git a/features/steps/project/active_tab.rb b/features/steps/project/active_tab.rb
index 58225032859..9f701840f1d 100644
--- a/features/steps/project/active_tab.rb
+++ b/features/steps/project/active_tab.rb
@@ -27,8 +27,8 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
end
end
- step 'I click the "Hooks" tab' do
- click_link('Webhooks')
+ step 'I click the "Integrations" tab' do
+ click_link('Integrations')
end
step 'I click the "Deploy Keys" tab' do
@@ -39,8 +39,8 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
ensure_active_sub_nav('Members')
end
- step 'the active sub nav should be Hooks' do
- ensure_active_sub_nav('Webhooks')
+ step 'the active sub nav should be Integrations' do
+ ensure_active_sub_nav('Integrations')
end
step 'the active sub nav should be Deploy Keys' do
diff --git a/features/steps/project/hooks.rb b/features/steps/project/hooks.rb
index 13c0713669a..37b608ffbd3 100644
--- a/features/steps/project/hooks.rb
+++ b/features/steps/project/hooks.rb
@@ -36,12 +36,12 @@ class Spinach::Features::ProjectHooks < Spinach::FeatureSteps
end
step 'I should see newly created hook' do
- expect(current_path).to eq namespace_project_hooks_path(current_project.namespace, current_project)
+ expect(current_path).to eq namespace_project_settings_integrations_path(current_project.namespace, current_project)
expect(page).to have_content(@url)
end
step 'I should see newly created hook with SSL verification enabled' do
- expect(current_path).to eq namespace_project_hooks_path(current_project.namespace, current_project)
+ expect(current_path).to eq namespace_project_settings_integrations_path(current_project.namespace, current_project)
expect(page).to have_content(@url)
expect(page).to have_content("SSL Verification: enabled")
end
@@ -57,7 +57,7 @@ class Spinach::Features::ProjectHooks < Spinach::FeatureSteps
end
step 'hook should be triggered' do
- expect(current_path).to eq namespace_project_hooks_path(current_project.namespace, current_project)
+ expect(current_path).to eq namespace_project_settings_integrations_path(current_project.namespace, current_project)
expect(page).to have_selector '.flash-notice',
text: 'Hook executed successfully: HTTP 200'
end
diff --git a/features/steps/project/services.rb b/features/steps/project/services.rb
index a4d29770922..772b07d0ad8 100644
--- a/features/steps/project/services.rb
+++ b/features/steps/project/services.rb
@@ -4,7 +4,7 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps
include SharedPaths
step 'I visit project "Shop" services page' do
- visit namespace_project_services_path(@project.namespace, @project)
+ visit namespace_project_settings_integrations_path(@project.namespace, @project)
end
step 'I should see list of available services' do
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index 670e6ca49a3..718cf924729 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -256,7 +256,7 @@ module SharedPaths
end
step 'I visit project hooks page' do
- visit namespace_project_hooks_path(@project.namespace, @project)
+ visit namespace_project_settings_integrations_path(@project.namespace, @project)
end
step 'I visit project deploy keys page' do
diff --git a/lib/gitlab/import_export/members_mapper.rb b/lib/gitlab/import_export/members_mapper.rb
index b790733f4a7..2405b94db50 100644
--- a/lib/gitlab/import_export/members_mapper.rb
+++ b/lib/gitlab/import_export/members_mapper.rb
@@ -1,13 +1,10 @@
module Gitlab
module ImportExport
class MembersMapper
- attr_reader :missing_author_ids
-
def initialize(exported_members:, user:, project:)
- @exported_members = exported_members
+ @exported_members = user.admin? ? exported_members : []
@user = user
@project = project
- @missing_author_ids = []
# This needs to run first, as second call would be from #map
# which means project members already exist.
@@ -39,7 +36,6 @@ module Gitlab
def missing_keys_tracking_hash
Hash.new do |_, key|
- @missing_author_ids << key
default_user_id
end
end
@@ -64,7 +60,7 @@ module Gitlab
end
def find_project_user_query(member)
- user_arel[:username].eq(member['user']['username']).or(user_arel[:email].eq(member['user']['email']))
+ user_arel[:email].eq(member['user']['email']).or(user_arel[:username].eq(member['user']['username']))
end
def user_arel
diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb
index 7a649f28340..19e43cce768 100644
--- a/lib/gitlab/import_export/relation_factory.rb
+++ b/lib/gitlab/import_export/relation_factory.rb
@@ -14,7 +14,7 @@ module Gitlab
priorities: :label_priorities,
label: :project_label }.freeze
- USER_REFERENCES = %w[author_id assignee_id updated_by_id user_id created_by_id merge_user_id].freeze
+ USER_REFERENCES = %w[author_id assignee_id updated_by_id user_id created_by_id merge_user_id resolved_by_id].freeze
PROJECT_REFERENCES = %w[project_id source_project_id gl_project_id target_project_id].freeze
@@ -80,17 +80,13 @@ module Gitlab
# is left.
def set_note_author
old_author_id = @relation_hash['author_id']
-
- # Users with admin access can map users
- @relation_hash['author_id'] = admin_user? ? @members_mapper.map[old_author_id] : @members_mapper.default_user_id
-
author = @relation_hash.delete('author')
- update_note_for_missing_author(author['name']) if missing_author?(old_author_id)
+ update_note_for_missing_author(author['name']) unless has_author?(old_author_id)
end
- def missing_author?(old_author_id)
- !admin_user? || @members_mapper.missing_author_ids.include?(old_author_id)
+ def has_author?(old_author_id)
+ admin_user? && @members_mapper.map.keys.include?(old_author_id)
end
def missing_author_note(updated_at, author_name)
diff --git a/spec/controllers/projects/settings/integrations_controller_spec.rb b/spec/controllers/projects/settings/integrations_controller_spec.rb
new file mode 100644
index 00000000000..e0f9a5b24a6
--- /dev/null
+++ b/spec/controllers/projects/settings/integrations_controller_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe Projects::Settings::IntegrationsController do
+ let(:project) { create(:project, :public) }
+ let(:user) { create(:user) }
+
+ before do
+ project.team << [user, :master]
+ sign_in(user)
+ end
+
+ describe 'GET show' do
+ it 'renders show with 200 status code' do
+ get :show, namespace_id: project.namespace, project_id: project
+
+ expect(response).to have_http_status(200)
+ expect(response).to render_template(:show)
+ end
+ end
+end
diff --git a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
index 3ac9b2e0ae0..16dcc487812 100644
--- a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
@@ -43,6 +43,14 @@ describe 'Dropdown assignee', js: true, feature: true do
expect(page).to have_css(js_dropdown_assignee, visible: true)
end
+ it 'shows assigned to me link' do
+ filtered_search.set('assignee:')
+
+ page.within js_dropdown_assignee do
+ expect(page).to have_content('Assigned to me')
+ end
+ end
+
it 'closes when the search bar is unfocused' do
find('body').click()
@@ -121,6 +129,14 @@ describe 'Dropdown assignee', js: true, feature: true do
filtered_search.set('assignee:')
end
+ it 'filters by current user' do
+ page.within js_dropdown_assignee do
+ click_button 'Assigned to me'
+ end
+
+ expect(filtered_search.value).to eq("assignee:#{user.to_reference}")
+ end
+
it 'fills in the assignee username when the assignee has not been filtered' do
click_assignee(user_jacob.name)
diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb
index ead43d6784a..1cdac520181 100644
--- a/spec/features/issues/filtered_search/filter_issues_spec.rb
+++ b/spec/features/issues/filtered_search/filter_issues_spec.rb
@@ -19,9 +19,12 @@ describe 'Filter issues', js: true, feature: true do
let!(:closed_issue) { create(:issue, title: 'bug that is closed', project: project, state: :closed) }
let(:filtered_search) { find('.filtered-search') }
- def input_filtered_search(search_term)
+ def input_filtered_search(search_term, submit: true)
filtered_search.set(search_term)
- filtered_search.send_keys(:enter)
+
+ if submit
+ filtered_search.send_keys(:enter)
+ end
end
def expect_filtered_search_input(input)
@@ -43,6 +46,10 @@ describe 'Filter issues', js: true, feature: true do
end
end
+ def select_search_at_index(pos)
+ evaluate_script("el = document.querySelector('.filtered-search'); el.focus(); el.setSelectionRange(#{pos}, #{pos});")
+ end
+
before do
project.team << [user, :master]
project.team << [user2, :master]
@@ -522,6 +529,44 @@ describe 'Filter issues', js: true, feature: true do
end
end
+ describe 'overwrites selected filter' do
+ it 'changes author' do
+ input_filtered_search("author:@#{user.username}", submit: false)
+
+ select_search_at_index(3)
+
+ page.within '#js-dropdown-author' do
+ click_button user2.username
+ end
+
+ expect(filtered_search.value).to eq("author:@#{user2.username}")
+ end
+
+ it 'changes label' do
+ input_filtered_search("author:@#{user.username} label:~#{bug_label.title}", submit: false)
+
+ select_search_at_index(27)
+
+ page.within '#js-dropdown-label' do
+ click_button label.name
+ end
+
+ expect(filtered_search.value).to eq("author:@#{user.username} label:~#{label.name}")
+ end
+
+ it 'changes label correctly space is in previous label' do
+ input_filtered_search("label:~\"#{multiple_words_label.title}\"", submit: false)
+
+ select_search_at_index(0)
+
+ page.within '#js-dropdown-label' do
+ click_button label.name
+ end
+
+ expect(filtered_search.value).to eq("label:~#{label.name}")
+ end
+ end
+
describe 'filter issues by text' do
context 'only text' do
it 'filters issues by searched text' do
diff --git a/spec/features/merge_requests/merge_immediately_with_pipeline_spec.rb b/spec/features/merge_requests/merge_immediately_with_pipeline_spec.rb
new file mode 100644
index 00000000000..f2f8f11ab28
--- /dev/null
+++ b/spec/features/merge_requests/merge_immediately_with_pipeline_spec.rb
@@ -0,0 +1,41 @@
+require 'spec_helper'
+
+feature 'Merge immediately', :feature, :js do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :public) }
+
+ let(:merge_request) do
+ create(:merge_request_with_diffs, source_project: project,
+ author: user,
+ title: 'Bug NS-04')
+ end
+
+ let(:pipeline) do
+ create(:ci_pipeline, project: project,
+ sha: merge_request.diff_head_sha,
+ ref: merge_request.source_branch)
+ end
+
+ before { project.team << [user, :master] }
+
+ context 'when there is active pipeline for merge request' do
+ background do
+ create(:ci_build, pipeline: pipeline)
+ end
+
+ before do
+ login_as user
+ visit namespace_project_merge_request_path(merge_request.project.namespace, merge_request.project, merge_request)
+ end
+
+ it 'enables merge immediately' do
+ page.within '.mr-widget-body' do
+ find('.dropdown-toggle').click
+
+ click_link 'Merge Immediately'
+
+ expect(find('.js-merge-button')).to have_content('Merge in progress')
+ end
+ end
+ end
+end
diff --git a/spec/features/merge_requests/merge_when_pipeline_succeeds_spec.rb b/spec/features/merge_requests/merge_when_pipeline_succeeds_spec.rb
index aa24a905001..2ea9c317bd1 100644
--- a/spec/features/merge_requests/merge_when_pipeline_succeeds_spec.rb
+++ b/spec/features/merge_requests/merge_when_pipeline_succeeds_spec.rb
@@ -32,19 +32,61 @@ feature 'Merge When Pipeline Succeeds', :feature, :js do
expect(page).to have_button "Merge When Pipeline Succeeds"
end
- context "Merge When Pipeline Succeeds enabled" do
- before do
- click_button "Merge When Pipeline Succeeds"
+ describe 'enabling Merge When Pipeline Succeeds' do
+ shared_examples 'Merge When Pipeline Succeeds activator' do
+ it 'activates the Merge When Pipeline Succeeds feature' do
+ click_button "Merge When Pipeline Succeeds"
+
+ expect(page).to have_content "Set by #{user.name} to be merged automatically when the pipeline succeeds."
+ expect(page).to have_content "The source branch will not be removed."
+ expect(page).to have_link "Cancel Automatic Merge"
+ visit_merge_request(merge_request) # Needed to refresh the page
+ expect(page).to have_content /enabled an automatic merge when the pipeline for \h{8} succeeds/i
+ end
end
- it 'activates Merge When Pipeline Succeeds feature' do
- expect(page).to have_link "Cancel Automatic Merge"
+ context "when enabled immediately" do
+ it_behaves_like 'Merge When Pipeline Succeeds activator'
+ end
+
+ context 'when enabled after pipeline status changed' do
+ before do
+ pipeline.run!
- expect(page).to have_content "Set by #{user.name} to be merged automatically when the pipeline succeeds."
- expect(page).to have_content "The source branch will not be removed."
+ # We depend on merge request widget being reloaded
+ # so we have to wait for asynchronous call to reload it
+ # and have_content expectation handles that.
+ #
+ expect(page).to have_content "Pipeline ##{pipeline.id} running"
+ end
+
+ it_behaves_like 'Merge When Pipeline Succeeds activator'
+ end
+
+ context 'when enabled after it was previously canceled' do
+ before do
+ click_button "Merge When Pipeline Succeeds"
+ click_link "Cancel Automatic Merge"
+ end
+
+ it_behaves_like 'Merge When Pipeline Succeeds activator'
+ end
- visit_merge_request(merge_request) # Needed to refresh the page
- expect(page).to have_content /enabled an automatic merge when the pipeline for \h{8} succeeds/i
+ context 'when it was enabled and then canceled' do
+ let(:merge_request) do
+ create(:merge_request_with_diffs,
+ :merge_when_build_succeeds,
+ source_project: project,
+ title: 'Bug NS-04',
+ author: user,
+ merge_user: user)
+ end
+
+ before do
+ click_link "Cancel Automatic Merge"
+ end
+
+ it_behaves_like 'Merge When Pipeline Succeeds activator'
end
end
end
diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb
index ecebabefff8..92d5a2fbc48 100644
--- a/spec/features/security/project/internal_access_spec.rb
+++ b/spec/features/security/project/internal_access_spec.rb
@@ -262,8 +262,8 @@ describe "Internal Project Access", feature: true do
it { is_expected.to be_denied_for(:visitor) }
end
- describe "GET /:project_path/hooks" do
- subject { namespace_project_hooks_path(project.namespace, project) }
+ describe "GET /:project_path/settings/integrations" do
+ subject { namespace_project_settings_integrations_path(project.namespace, project) }
it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:owner).of(project) }
diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb
index 9bc59a7c4f9..b616e488487 100644
--- a/spec/features/security/project/private_access_spec.rb
+++ b/spec/features/security/project/private_access_spec.rb
@@ -234,8 +234,8 @@ describe "Private Project Access", feature: true do
it { is_expected.to be_denied_for(:visitor) }
end
- describe "GET /:project_path/hooks" do
- subject { namespace_project_hooks_path(project.namespace, project) }
+ describe "GET /:project_path/namespace/hooks" do
+ subject { namespace_project_settings_integrations_path(project.namespace, project) }
it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:owner).of(project) }
diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb
index a8d43b3d581..ded85e837f4 100644
--- a/spec/features/security/project/public_access_spec.rb
+++ b/spec/features/security/project/public_access_spec.rb
@@ -400,8 +400,8 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for(:visitor) }
end
- describe "GET /:project_path/hooks" do
- subject { namespace_project_hooks_path(project.namespace, project) }
+ describe "GET /:project_path/settings/integrations" do
+ subject { namespace_project_settings_integrations_path(project.namespace, project) }
it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:owner).of(project) }
diff --git a/spec/finders/move_to_project_finder_spec.rb b/spec/finders/move_to_project_finder_spec.rb
index fdce4e714ff..8488dbd2a16 100644
--- a/spec/finders/move_to_project_finder_spec.rb
+++ b/spec/finders/move_to_project_finder_spec.rb
@@ -2,13 +2,13 @@ require 'spec_helper'
describe MoveToProjectFinder do
let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
- let(:no_access_project) { create(:project) }
- let(:guest_project) { create(:project) }
- let(:reporter_project) { create(:project) }
- let(:developer_project) { create(:project) }
- let(:master_project) { create(:project) }
+ let(:no_access_project) { create(:empty_project) }
+ let(:guest_project) { create(:empty_project) }
+ let(:reporter_project) { create(:empty_project) }
+ let(:developer_project) { create(:empty_project) }
+ let(:master_project) { create(:empty_project) }
subject { described_class.new(user) }
@@ -37,7 +37,7 @@ describe MoveToProjectFinder do
it 'does not return archived projects' do
reporter_project.team << [user, :reporter]
reporter_project.update_attributes(archived: true)
- other_reporter_project = create(:project)
+ other_reporter_project = create(:empty_project)
other_reporter_project.team << [user, :reporter]
expect(subject.execute(project).to_a).to eq([other_reporter_project])
@@ -46,7 +46,7 @@ describe MoveToProjectFinder do
it 'does not return projects for which issues are disabled' do
reporter_project.team << [user, :reporter]
reporter_project.update_attributes(issues_enabled: false)
- other_reporter_project = create(:project)
+ other_reporter_project = create(:empty_project)
other_reporter_project.team << [user, :reporter]
expect(subject.execute(project).to_a).to eq([other_reporter_project])
@@ -83,10 +83,10 @@ describe MoveToProjectFinder do
end
it 'returns projects matching a search query' do
- foo_project = create(:project)
+ foo_project = create(:empty_project)
foo_project.team << [user, :master]
- wadus_project = create(:project, name: 'wadus')
+ wadus_project = create(:empty_project, name: 'wadus')
wadus_project.team << [user, :master]
expect(subject.execute(project).to_a).to eq([wadus_project, foo_project])
diff --git a/spec/javascripts/filtered_search/dropdown_utils_spec.js.es6 b/spec/javascripts/filtered_search/dropdown_utils_spec.js.es6
index ce61b73aa8a..19bd8d53219 100644
--- a/spec/javascripts/filtered_search/dropdown_utils_spec.js.es6
+++ b/spec/javascripts/filtered_search/dropdown_utils_spec.js.es6
@@ -31,41 +31,68 @@
});
describe('filterWithSymbol', () => {
+ let input;
const item = {
title: '@root',
};
+ beforeEach(() => {
+ setFixtures(`
+ <input type="text" id="test" />
+ `);
+
+ input = document.getElementById('test');
+ });
+
it('should filter without symbol', () => {
- const updatedItem = gl.DropdownUtils.filterWithSymbol('@', item, ':roo');
+ input.value = ':roo';
+
+ const updatedItem = gl.DropdownUtils.filterWithSymbol('@', input, item);
expect(updatedItem.droplab_hidden).toBe(false);
});
it('should filter with symbol', () => {
- const updatedItem = gl.DropdownUtils.filterWithSymbol('@', item, ':@roo');
+ input.value = '@roo';
+
+ const updatedItem = gl.DropdownUtils.filterWithSymbol('@', input, item);
expect(updatedItem.droplab_hidden).toBe(false);
});
it('should filter with colon', () => {
- const updatedItem = gl.DropdownUtils.filterWithSymbol('@', item, ':');
+ input.value = 'roo';
+
+ const updatedItem = gl.DropdownUtils.filterWithSymbol('@', input, item);
expect(updatedItem.droplab_hidden).toBe(false);
});
});
describe('filterHint', () => {
+ let input;
+
+ beforeEach(() => {
+ setFixtures(`
+ <input type="text" id="test" />
+ `);
+
+ input = document.getElementById('test');
+ });
+
it('should filter', () => {
- let updatedItem = gl.DropdownUtils.filterHint({
+ input.value = 'l';
+ let updatedItem = gl.DropdownUtils.filterHint(input, {
hint: 'label',
- }, 'l');
+ });
expect(updatedItem.droplab_hidden).toBe(false);
- updatedItem = gl.DropdownUtils.filterHint({
+ input.value = 'o';
+ updatedItem = gl.DropdownUtils.filterHint(input, {
hint: 'label',
}, 'o');
expect(updatedItem.droplab_hidden).toBe(true);
});
it('should return droplab_hidden false when item has no hint', () => {
- const updatedItem = gl.DropdownUtils.filterHint({}, '');
+ const updatedItem = gl.DropdownUtils.filterHint(input, {}, '');
expect(updatedItem.droplab_hidden).toBe(false);
});
});
diff --git a/spec/lib/gitlab/import_export/members_mapper_spec.rb b/spec/lib/gitlab/import_export/members_mapper_spec.rb
index 1cb02f8e318..b069696b5c7 100644
--- a/spec/lib/gitlab/import_export/members_mapper_spec.rb
+++ b/spec/lib/gitlab/import_export/members_mapper_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Gitlab::ImportExport::MembersMapper, services: true do
describe 'map members' do
- let(:user) { create(:user, authorized_projects_populated: true) }
+ let(:user) { create(:admin, authorized_projects_populated: true) }
let(:project) { create(:project, :public, name: 'searchable_project') }
let(:user2) { create(:user, authorized_projects_populated: true) }
let(:exported_user_id) { 99 }
@@ -24,7 +24,7 @@ describe Gitlab::ImportExport::MembersMapper, services: true do
{
"id" => exported_user_id,
"email" => user2.email,
- "username" => user2.username
+ "username" => 'test'
}
},
{
@@ -48,6 +48,10 @@ describe Gitlab::ImportExport::MembersMapper, services: true do
exported_members: exported_members, user: user, project: project)
end
+ it 'includes the exported user ID in the map' do
+ expect(members_mapper.map.keys).to include(exported_user_id)
+ end
+
it 'maps a project member' do
expect(members_mapper.map[exported_user_id]).to eq(user2.id)
end
@@ -56,12 +60,6 @@ describe Gitlab::ImportExport::MembersMapper, services: true do
expect(members_mapper.map[-1]).to eq(user.id)
end
- it 'updates missing author IDs on missing project member' do
- members_mapper.map[-1]
-
- expect(members_mapper.missing_author_ids.first).to eq(-1)
- end
-
it 'has invited members with no user' do
members_mapper.map
@@ -74,5 +72,25 @@ describe Gitlab::ImportExport::MembersMapper, services: true do
expect(user.authorized_project?(project)).to be true
expect(user2.authorized_project?(project)).to be true
end
+
+ context 'user is not an admin' do
+ let(:user) { create(:user, authorized_projects_populated: true) }
+
+ it 'does not map a project member' do
+ expect(members_mapper.map[exported_user_id]).to eq(user.id)
+ end
+
+ it 'defaults to importer project member if it does not exist' do
+ expect(members_mapper.map[-1]).to eq(user.id)
+ end
+ end
+
+ context 'chooses the one with an email first' do
+ let(:user3) { create(:user, username: 'test') }
+
+ it 'maps the project member that has a matching email first' do
+ expect(members_mapper.map[exported_user_id]).to eq(user2.id)
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/import_export/relation_factory_spec.rb b/spec/lib/gitlab/import_export/relation_factory_spec.rb
index 3aa492a8ab1..db0084d6823 100644
--- a/spec/lib/gitlab/import_export/relation_factory_spec.rb
+++ b/spec/lib/gitlab/import_export/relation_factory_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe Gitlab::ImportExport::RelationFactory, lib: true do
let(:project) { create(:empty_project) }
let(:members_mapper) { double('members_mapper').as_null_object }
- let(:user) { create(:user) }
+ let(:user) { create(:admin) }
let(:created_object) do
described_class.create(relation_sym: relation_sym,
relation_hash: relation_hash,
@@ -122,4 +122,60 @@ describe Gitlab::ImportExport::RelationFactory, lib: true do
expect(created_object.values).not_to include(99)
end
end
+
+ context 'Notes user references' do
+ let(:relation_sym) { :notes }
+ let(:new_user) { create(:user) }
+ let(:exported_member) do
+ {
+ "id" => 111,
+ "access_level" => 30,
+ "source_id" => 1,
+ "source_type" => "Project",
+ "user_id" => 3,
+ "notification_level" => 3,
+ "created_at" => "2016-11-18T09:29:42.634Z",
+ "updated_at" => "2016-11-18T09:29:42.634Z",
+ "user" => {
+ "id" => 999,
+ "email" => new_user.email,
+ "username" => new_user.username
+ }
+ }
+ end
+
+ let(:relation_hash) do
+ {
+ "id" => 4947,
+ "note" => "merged",
+ "noteable_type" => "MergeRequest",
+ "author_id" => 999,
+ "created_at" => "2016-11-18T09:29:42.634Z",
+ "updated_at" => "2016-11-18T09:29:42.634Z",
+ "project_id" => 1,
+ "attachment" => {
+ "url" => nil
+ },
+ "noteable_id" => 377,
+ "system" => true,
+ "author" => {
+ "name" => "Administrator"
+ },
+ "events" => [
+
+ ]
+ }
+ end
+
+ let(:members_mapper) do
+ Gitlab::ImportExport::MembersMapper.new(
+ exported_members: [exported_member],
+ user: user,
+ project: project)
+ end
+
+ it 'maps the right author to the imported note' do
+ expect(created_object.author).to eq(new_user)
+ end
+ end
end
diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb
index 5eaddd822be..7c40cfd8253 100644
--- a/spec/models/key_spec.rb
+++ b/spec/models/key_spec.rb
@@ -30,11 +30,30 @@ describe Key, models: true do
end
describe "#update_last_used_at" do
- it "enqueues a UseKeyWorker job" do
- key = create(:key)
+ let(:key) { create(:key) }
+
+ context 'when key was not updated during the last day' do
+ before do
+ allow_any_instance_of(Gitlab::ExclusiveLease).to receive(:try_obtain).
+ and_return('000000')
+ end
+
+ it 'enqueues a UseKeyWorker job' do
+ expect(UseKeyWorker).to receive(:perform_async).with(key.id)
+ key.update_last_used_at
+ end
+ end
+
+ context 'when key was updated during the last day' do
+ before do
+ allow_any_instance_of(Gitlab::ExclusiveLease).to receive(:try_obtain).
+ and_return(false)
+ end
- expect(UseKeyWorker).to receive(:perform_async).with(key.id)
- key.update_last_used_at
+ it 'does not enqueue a UseKeyWorker job' do
+ expect(UseKeyWorker).not_to receive(:perform_async)
+ key.update_last_used_at
+ end
end
end
end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 38c80ba53ad..32ed1e96749 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -65,7 +65,7 @@ describe MergeRequest, models: true do
end
describe '#target_branch_sha' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
subject { create(:merge_request, source_project: project, target_project: project) }
@@ -150,7 +150,7 @@ describe MergeRequest, models: true do
end
it 'supports a cross-project reference' do
- another_project = build(:project, name: 'another-project', namespace: project.namespace)
+ another_project = build(:empty_project, name: 'another-project', namespace: project.namespace)
expect(merge_request.to_reference(another_project)).to eq "sample-project!1"
end
@@ -245,8 +245,8 @@ describe MergeRequest, models: true do
describe '#for_fork?' do
it 'returns true if the merge request is for a fork' do
- subject.source_project = create(:project, namespace: create(:group))
- subject.target_project = create(:project, namespace: create(:group))
+ subject.source_project = build_stubbed(:empty_project, namespace: create(:group))
+ subject.target_project = build_stubbed(:empty_project, namespace: create(:group))
expect(subject.for_fork?).to be_truthy
end
@@ -501,8 +501,8 @@ describe MergeRequest, models: true do
end
describe '#diverged_commits_count' do
- let(:project) { create(:project) }
- let(:fork_project) { create(:project, forked_from_project: project) }
+ let(:project) { create(:project, :repository) }
+ let(:fork_project) { create(:project, :repository, forked_from_project: project) }
context 'when the target branch does not exist anymore' do
subject { create(:merge_request, source_project: project, target_project: project) }
@@ -727,7 +727,7 @@ describe MergeRequest, models: true do
end
describe '#participants' do
- let(:project) { create(:project, :public) }
+ let(:project) { create(:empty_project, :public) }
let(:mr) do
create(:merge_request, source_project: project, target_project: project)
@@ -768,7 +768,7 @@ describe MergeRequest, models: true do
end
describe '#check_if_can_be_merged' do
- let(:project) { create(:project, only_allow_merge_if_build_succeeds: true) }
+ let(:project) { create(:empty_project, only_allow_merge_if_build_succeeds: true) }
subject { create(:merge_request, source_project: project, merge_status: :unchecked) }
@@ -789,7 +789,7 @@ describe MergeRequest, models: true do
it 'becomes unmergeable' do
expect { subject.check_if_can_be_merged }.to change { subject.merge_status }.to('cannot_be_merged')
end
-
+
it 'creates Todo on unmergeability' do
expect_any_instance_of(TodoService).to receive(:merge_request_became_unmergeable).with(subject)
@@ -810,7 +810,7 @@ describe MergeRequest, models: true do
end
describe '#mergeable?' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
subject { create(:merge_request, source_project: project) }
@@ -830,7 +830,7 @@ describe MergeRequest, models: true do
end
describe '#mergeable_state?' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
subject { create(:merge_request, source_project: project) }
@@ -957,7 +957,7 @@ describe MergeRequest, models: true do
let(:merge_request) { create(:merge_request_with_diff_notes, source_project: project) }
context 'when project.only_allow_merge_if_all_discussions_are_resolved == true' do
- let(:project) { create(:project, only_allow_merge_if_all_discussions_are_resolved: true) }
+ let(:project) { create(:project, :repository, only_allow_merge_if_all_discussions_are_resolved: true) }
context 'with all discussions resolved' do
before do
@@ -991,7 +991,7 @@ describe MergeRequest, models: true do
end
context 'when project.only_allow_merge_if_all_discussions_are_resolved == false' do
- let(:project) { create(:project, only_allow_merge_if_all_discussions_are_resolved: false) }
+ let(:project) { create(:project, :repository, only_allow_merge_if_all_discussions_are_resolved: false) }
context 'with unresolved discussions' do
before do
@@ -1006,7 +1006,7 @@ describe MergeRequest, models: true do
end
describe "#environments" do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:merge_request) { create(:merge_request, source_project: project) }
context 'with multiple environments' do
@@ -1024,7 +1024,7 @@ describe MergeRequest, models: true do
context 'with environments on source project' do
let(:source_project) do
- create(:project) do |fork_project|
+ create(:project, :repository) do |fork_project|
fork_project.create_forked_project_link(forked_to_project_id: fork_project.id, forked_from_project_id: project.id)
end
end
@@ -1401,8 +1401,8 @@ describe MergeRequest, models: true do
end
describe "#source_project_missing?" do
- let(:project) { create(:project) }
- let(:fork_project) { create(:project, forked_from_project: project) }
+ let(:project) { create(:empty_project) }
+ let(:fork_project) { create(:empty_project, forked_from_project: project) }
let(:user) { create(:user) }
let(:unlink_project) { Projects::UnlinkForkService.new(fork_project, user) }
@@ -1439,8 +1439,8 @@ describe MergeRequest, models: true do
end
describe "#closed_without_fork?" do
- let(:project) { create(:project) }
- let(:fork_project) { create(:project, forked_from_project: project) }
+ let(:project) { create(:empty_project) }
+ let(:fork_project) { create(:empty_project, forked_from_project: project) }
let(:user) { create(:user) }
let(:unlink_project) { Projects::UnlinkForkService.new(fork_project, user) }
@@ -1485,9 +1485,9 @@ describe MergeRequest, models: true do
end
context 'forked project' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
let(:user) { create(:user) }
- let(:fork_project) { create(:project, forked_from_project: project, namespace: user.namespace) }
+ let(:fork_project) { create(:empty_project, forked_from_project: project, namespace: user.namespace) }
let!(:merge_request) do
create(:closed_merge_request,
@@ -1531,7 +1531,7 @@ describe MergeRequest, models: true do
status: status)
end
- let(:project) { create(:project, :public, only_allow_merge_if_build_succeeds: true) }
+ let(:project) { create(:project, :public, :repository, only_allow_merge_if_build_succeeds: true) }
let(:developer) { create(:user) }
let(:user) { create(:user) }
let(:merge_request) { create(:merge_request, source_project: project) }
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index e93a4e62244..8048e86fc3a 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -73,9 +73,7 @@ describe Project, models: true do
context 'after initialized' do
it "has a project_feature" do
- project = FactoryGirl.build(:project)
-
- expect(project.project_feature.present?).to be_present
+ expect(Project.new.project_feature).to be_present
end
end
@@ -129,7 +127,7 @@ describe Project, models: true do
end
describe 'validation' do
- let!(:project) { create(:project) }
+ let!(:project) { create(:empty_project) }
it { is_expected.to validate_presence_of(:name) }
it { is_expected.to validate_uniqueness_of(:name).scoped_to(:namespace_id) }
@@ -148,7 +146,7 @@ describe Project, models: true do
it { is_expected.to validate_presence_of(:repository_storage) }
it 'does not allow new projects beyond user limits' do
- project2 = build(:project)
+ project2 = build(:empty_project)
allow(project2).to receive(:creator).and_return(double(can_create_project?: false, projects_limit: 0).as_null_object)
expect(project2).not_to be_valid
expect(project2.errors[:limit_reached].first).to match(/Personal project creation is not allowed/)
@@ -157,7 +155,7 @@ describe Project, models: true do
describe 'wiki path conflict' do
context "when the new path has been used by the wiki of other Project" do
it 'has an error on the name attribute' do
- new_project = build_stubbed(:project, namespace_id: project.namespace_id, path: "#{project.path}.wiki")
+ new_project = build_stubbed(:empty_project, namespace_id: project.namespace_id, path: "#{project.path}.wiki")
expect(new_project).not_to be_valid
expect(new_project.errors[:name].first).to eq('has already been taken')
@@ -166,8 +164,8 @@ describe Project, models: true do
context "when the new wiki path has been used by the path of other Project" do
it 'has an error on the name attribute' do
- project_with_wiki_suffix = create(:project, path: 'foo.wiki')
- new_project = build_stubbed(:project, namespace_id: project_with_wiki_suffix.namespace_id, path: 'foo')
+ project_with_wiki_suffix = create(:empty_project, path: 'foo.wiki')
+ new_project = build_stubbed(:empty_project, namespace_id: project_with_wiki_suffix.namespace_id, path: 'foo')
expect(new_project).not_to be_valid
expect(new_project.errors[:name].first).to eq('has already been taken')
@@ -176,7 +174,7 @@ describe Project, models: true do
end
context 'repository storages inclussion' do
- let(:project2) { build(:project, repository_storage: 'missing') }
+ let(:project2) { build(:empty_project, repository_storage: 'missing') }
before do
storages = { 'custom' => 'tmp/tests/custom_repositories' }
@@ -352,7 +350,7 @@ describe Project, models: true do
end
describe '#repository_storage_path' do
- let(:project) { create(:project, repository_storage: 'custom') }
+ let(:project) { create(:empty_project, repository_storage: 'custom') }
before do
FileUtils.mkdir('tmp/tests/custom_repositories')
@@ -412,7 +410,7 @@ describe Project, models: true do
describe 'last_activity methods' do
let(:timestamp) { 2.hours.ago }
# last_activity_at gets set to created_at upon creation
- let(:project) { create(:project, created_at: timestamp, updated_at: timestamp) }
+ let(:project) { create(:empty_project, created_at: timestamp, updated_at: timestamp) }
describe 'last_activity' do
it 'alias last_activity to last_event' do
@@ -496,7 +494,7 @@ describe Project, models: true do
context 'with namespace' do
before do
@group = create :group, name: 'gitlab'
- @project = create(:project, name: 'gitlabhq', namespace: @group)
+ @project = create(:empty_project, name: 'gitlabhq', namespace: @group)
end
it { expect(@project.to_param).to eq('gitlabhq') }
@@ -522,7 +520,7 @@ describe Project, models: true do
end
describe '#repository' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
it 'returns valid repo' do
expect(project.repository).to be_kind_of(Repository)
@@ -530,20 +528,22 @@ describe Project, models: true do
end
describe '#default_issues_tracker?' do
- let(:project) { create(:project) }
- let(:ext_project) { create(:redmine_project) }
-
it "is true if used internal tracker" do
+ project = build(:empty_project)
+
expect(project.default_issues_tracker?).to be_truthy
end
it "is false if used other tracker" do
- expect(ext_project.default_issues_tracker?).to be_falsey
+ # NOTE: The current nature of this factory requires persistence
+ project = create(:redmine_project)
+
+ expect(project.default_issues_tracker?).to be_falsey
end
end
describe '#external_issue_tracker' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
let(:ext_project) { create(:redmine_project) }
context 'on existing projects with no value for has_external_issue_tracker' do
@@ -578,7 +578,7 @@ describe Project, models: true do
end
describe '#cache_has_external_issue_tracker' do
- let(:project) { create(:project, has_external_issue_tracker: nil) }
+ let(:project) { create(:empty_project, has_external_issue_tracker: nil) }
it 'stores true if there is any external_issue_tracker' do
services = double(:service, external_issue_trackers: [RedmineService.new])
@@ -600,9 +600,9 @@ describe Project, models: true do
end
describe '#has_wiki?' do
- let(:no_wiki_project) { create(:project, wiki_access_level: ProjectFeature::DISABLED, has_external_wiki: false) }
- let(:wiki_enabled_project) { create(:project) }
- let(:external_wiki_project) { create(:project, has_external_wiki: true) }
+ let(:no_wiki_project) { create(:empty_project, wiki_access_level: ProjectFeature::DISABLED, has_external_wiki: false) }
+ let(:wiki_enabled_project) { create(:empty_project) }
+ let(:external_wiki_project) { create(:empty_project, has_external_wiki: true) }
it 'returns true if project is wiki enabled or has external wiki' do
expect(wiki_enabled_project).to have_wiki
@@ -612,7 +612,7 @@ describe Project, models: true do
end
describe '#external_wiki' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
context 'with an active external wiki' do
before do
@@ -663,7 +663,7 @@ describe Project, models: true do
end
describe '#open_branches' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
before do
project.protected_branches.create(name: 'master')
@@ -685,7 +685,7 @@ describe Project, models: true do
it 'counts stars from multiple users' do
user1 = create :user
user2 = create :user
- project = create :project, :public
+ project = create(:empty_project, :public)
expect(project.star_count).to eq(0)
@@ -707,8 +707,8 @@ describe Project, models: true do
it 'counts stars on the right project' do
user = create :user
- project1 = create :project, :public
- project2 = create :project, :public
+ project1 = create(:empty_project, :public)
+ project2 = create(:empty_project, :public)
expect(project1.star_count).to eq(0)
expect(project2.star_count).to eq(0)
@@ -740,7 +740,7 @@ describe Project, models: true do
end
describe '#avatar_type' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
it 'is true if avatar is image' do
project.update_attribute(:avatar, 'uploads/avatar.png')
@@ -756,7 +756,7 @@ describe Project, models: true do
describe '#avatar_url' do
subject { project.avatar_url }
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
context 'When avatar file is uploaded' do
before do
@@ -791,7 +791,7 @@ describe Project, models: true do
end
describe '#pipeline_for' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let!(:pipeline) { create_pipeline }
shared_examples 'giving the correct pipeline' do
@@ -825,7 +825,7 @@ describe Project, models: true do
end
describe '#builds_enabled' do
- let(:project) { create :project }
+ let(:project) { create(:empty_project) }
subject { project.builds_enabled }
@@ -877,7 +877,7 @@ describe Project, models: true do
end
describe '.visible_to_user' do
- let!(:project) { create(:project, :private) }
+ let!(:project) { create(:empty_project, :private) }
let!(:user) { create(:user) }
subject { described_class.visible_to_user(user) }
@@ -975,7 +975,7 @@ describe Project, models: true do
end
describe '#visibility_level_allowed?' do
- let(:project) { create(:project, :internal) }
+ let(:project) { create(:empty_project, :internal) }
context 'when checking on non-forked project' do
it { expect(project.visibility_level_allowed?(Gitlab::VisibilityLevel::PRIVATE)).to be_truthy }
@@ -984,8 +984,8 @@ describe Project, models: true do
end
context 'when checking on forked project' do
- let(:project) { create(:project, :internal) }
- let(:forked_project) { create(:project, forked_from_project: project) }
+ let(:project) { create(:empty_project, :internal) }
+ let(:forked_project) { create(:empty_project, forked_from_project: project) }
it { expect(forked_project.visibility_level_allowed?(Gitlab::VisibilityLevel::PRIVATE)).to be_truthy }
it { expect(forked_project.visibility_level_allowed?(Gitlab::VisibilityLevel::INTERNAL)).to be_truthy }
@@ -994,7 +994,7 @@ describe Project, models: true do
end
describe '.search' do
- let(:project) { create(:project, description: 'kitten mittens') }
+ let(:project) { create(:empty_project, description: 'kitten mittens') }
it 'returns projects with a matching name' do
expect(described_class.search(project.name)).to eq([project])
@@ -1052,7 +1052,7 @@ describe Project, models: true do
end
describe '#rename_repo' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:gitlab_shell) { Gitlab::Shell.new }
before do
@@ -1102,7 +1102,7 @@ describe Project, models: true do
end
describe '#expire_caches_before_rename' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:repo) { double(:repo, exists?: true) }
let(:wiki) { double(:wiki, exists?: true) }
@@ -1123,7 +1123,7 @@ describe Project, models: true do
end
describe '.search_by_title' do
- let(:project) { create(:project, name: 'kittens') }
+ let(:project) { create(:empty_project, name: 'kittens') }
it 'returns projects with a matching name' do
expect(described_class.search_by_title(project.name)).to eq([project])
@@ -1142,8 +1142,8 @@ describe Project, models: true do
let(:private_group) { create(:group, visibility_level: 0) }
let(:internal_group) { create(:group, visibility_level: 10) }
- let(:private_project) { create :project, :private, group: private_group }
- let(:internal_project) { create :project, :internal, group: internal_group }
+ let(:private_project) { create :empty_project, :private, group: private_group }
+ let(:internal_project) { create :empty_project, :internal, group: internal_group }
context 'when group is private project can not be internal' do
it { expect(private_project.visibility_level_allowed?(Gitlab::VisibilityLevel::INTERNAL)).to be_falsey }
@@ -1155,7 +1155,7 @@ describe Project, models: true do
end
describe '#create_repository' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:shell) { Gitlab::Shell.new }
before do
@@ -1197,7 +1197,7 @@ describe Project, models: true do
describe '#protected_branch?' do
context 'existing project' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
it 'returns true when the branch matches a protected branch via direct match' do
create(:protected_branch, project: project, name: "foo")
@@ -1381,7 +1381,7 @@ describe Project, models: true do
name: name)
end
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:pipeline) { create_pipeline }
context 'with many builds' do
@@ -1461,7 +1461,7 @@ describe Project, models: true do
end
context 'not forked' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
it 'schedules a RepositoryImportWorker job' do
expect(RepositoryImportWorker).to receive(:perform_async).with(project.id)
@@ -1472,19 +1472,19 @@ describe Project, models: true do
end
describe '#gitlab_project_import?' do
- subject(:project) { build(:project, import_type: 'gitlab_project') }
+ subject(:project) { build(:empty_project, import_type: 'gitlab_project') }
it { expect(project.gitlab_project_import?).to be true }
end
describe '#gitea_import?' do
- subject(:project) { build(:project, import_type: 'gitea') }
+ subject(:project) { build(:empty_project, import_type: 'gitea') }
it { expect(project.gitea_import?).to be true }
end
describe '#lfs_enabled?' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
shared_examples 'project overrides group' do
it 'returns true when enabled in project' do
@@ -1546,7 +1546,7 @@ describe Project, models: true do
end
describe '#change_head' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
it 'calls the before_change_head and after_change_head methods' do
expect(project.repository).to receive(:before_change_head)
@@ -1574,7 +1574,7 @@ describe Project, models: true do
end
describe '#pushes_since_gc' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
after do
project.reset_pushes_since_gc
@@ -1596,7 +1596,7 @@ describe Project, models: true do
end
describe '#increment_pushes_since_gc' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
after do
project.reset_pushes_since_gc
@@ -1610,7 +1610,7 @@ describe Project, models: true do
end
describe '#reset_pushes_since_gc' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
after do
project.reset_pushes_since_gc
@@ -1626,7 +1626,7 @@ describe Project, models: true do
end
describe '#environments_for' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:environment) { create(:environment, project: project) }
context 'tagged deployment' do
@@ -1678,7 +1678,7 @@ describe Project, models: true do
end
describe '#environments_recently_updated_on_branch' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:environment) { create(:environment, project: project) }
context 'when last deployment to environment is the most recent one' do
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 8b20ee81614..ca3d4ff0aa9 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -48,7 +48,7 @@ describe User, models: true do
describe '#project_members' do
it 'does not include project memberships for which user is a requester' do
user = create(:user)
- project = create(:project, :public, :access_requestable)
+ project = create(:empty_project, :public, :access_requestable)
project.request_access(user)
expect(user.project_members).to be_empty
@@ -386,13 +386,15 @@ describe User, models: true do
describe 'projects' do
before do
- @user = create :user
- @project = create :project, namespace: @user.namespace
- @project_2 = create :project, group: create(:group) # Grant MASTER access to the user
- @project_3 = create :project, group: create(:group) # Grant DEVELOPER access to the user
+ @user = create(:user)
- @project_2.team << [@user, :master]
- @project_3.team << [@user, :developer]
+ @project = create(:empty_project, namespace: @user.namespace)
+ @project_2 = create(:empty_project, group: create(:group)) do |project|
+ project.add_master(@user)
+ end
+ @project_3 = create(:empty_project, group: create(:group)) do |project|
+ project.add_developer(@user)
+ end
end
it { expect(@user.authorized_projects).to include(@project) }
@@ -435,7 +437,7 @@ describe User, models: true do
describe 'namespaced' do
before do
@user = create :user
- @project = create :project, namespace: @user.namespace
+ @project = create(:empty_project, namespace: @user.namespace)
end
it { expect(@user.several_namespaces?).to be_falsey }
@@ -517,7 +519,7 @@ describe User, models: true do
before do
User.delete_all
@user = create :user
- @project = create :project
+ @project = create(:empty_project)
end
it { expect(User.not_in_project(@project)).to include(@user, @project.owner) }
@@ -927,8 +929,8 @@ describe User, models: true do
describe "#starred?" do
it "determines if user starred a project" do
user = create :user
- project1 = create :project, :public
- project2 = create :project, :public
+ project1 = create(:empty_project, :public)
+ project2 = create(:empty_project, :public)
expect(user.starred?(project1)).to be_falsey
expect(user.starred?(project2)).to be_falsey
@@ -954,7 +956,7 @@ describe User, models: true do
describe "#toggle_star" do
it "toggles stars" do
user = create :user
- project = create :project, :public
+ project = create(:empty_project, :public)
expect(user.starred?(project)).to be_falsey
user.toggle_star(project)
@@ -994,9 +996,9 @@ describe User, models: true do
describe "#contributed_projects" do
subject { create(:user) }
- let!(:project1) { create(:project) }
- let!(:project2) { create(:project, forked_from_project: project3) }
- let!(:project3) { create(:project) }
+ let!(:project1) { create(:empty_project) }
+ let!(:project2) { create(:empty_project, forked_from_project: project3) }
+ let!(:project3) { create(:empty_project) }
let!(:merge_request) { create(:merge_request, source_project: project2, target_project: project3, author: subject) }
let!(:push_event) { create(:event, action: Event::PUSHED, project: project1, target: project1, author: subject) }
let!(:merge_event) { create(:event, action: Event::CREATED, project: project3, target: merge_request, author: subject) }
@@ -1038,8 +1040,8 @@ describe User, models: true do
describe "#recent_push" do
subject { create(:user) }
- let!(:project1) { create(:project) }
- let!(:project2) { create(:project, forked_from_project: project1) }
+ let!(:project1) { create(:project, :repository) }
+ let!(:project2) { create(:project, :repository, forked_from_project: project1) }
let!(:push_data) do
Gitlab::DataBuilder::Push.build_sample(project2, subject)
end
@@ -1113,7 +1115,7 @@ describe User, models: true do
it "includes user's personal projects" do
user = create(:user)
- project = create(:project, :private, namespace: user.namespace)
+ project = create(:empty_project, :private, namespace: user.namespace)
expect(user.authorized_projects).to include(project)
end
@@ -1121,7 +1123,7 @@ describe User, models: true do
it "includes personal projects user has been given access to" do
user1 = create(:user)
user2 = create(:user)
- project = create(:project, :private, namespace: user1.namespace)
+ project = create(:empty_project, :private, namespace: user1.namespace)
project.team << [user2, Gitlab::Access::DEVELOPER]
@@ -1130,7 +1132,7 @@ describe User, models: true do
it "includes projects of groups user has been added to" do
group = create(:group)
- project = create(:project, group: group)
+ project = create(:empty_project, group: group)
user = create(:user)
group.add_developer(user)
@@ -1140,7 +1142,7 @@ describe User, models: true do
it "does not include projects of groups user has been removed from" do
group = create(:group)
- project = create(:project, group: group)
+ project = create(:empty_project, group: group)
user = create(:user)
member = group.add_developer(user)
@@ -1152,7 +1154,7 @@ describe User, models: true do
it "includes projects shared with user's group" do
user = create(:user)
- project = create(:project, :private)
+ project = create(:empty_project, :private)
group = create(:group)
group.add_reporter(user)
@@ -1164,7 +1166,7 @@ describe User, models: true do
it "does not include destroyed projects user had access to" do
user1 = create(:user)
user2 = create(:user)
- project = create(:project, :private, namespace: user1.namespace)
+ project = create(:empty_project, :private, namespace: user1.namespace)
project.team << [user2, Gitlab::Access::DEVELOPER]
expect(user2.authorized_projects).to include(project)
@@ -1175,7 +1177,7 @@ describe User, models: true do
it "does not include projects of destroyed groups user had access to" do
group = create(:group)
- project = create(:project, namespace: group)
+ project = create(:empty_project, namespace: group)
user = create(:user)
group.add_developer(user)
@@ -1190,14 +1192,9 @@ describe User, models: true do
let(:user) { create(:user) }
it 'includes projects for which the user access level is above or equal to reporter' do
- create(:project)
- reporter_project = create(:project)
- developer_project = create(:project)
- master_project = create(:project)
-
- reporter_project.team << [user, :reporter]
- developer_project.team << [user, :developer]
- master_project.team << [user, :master]
+ reporter_project = create(:empty_project) { |p| p.add_reporter(user) }
+ developer_project = create(:empty_project) { |p| p.add_developer(user) }
+ master_project = create(:empty_project) { |p| p.add_master(user) }
expect(user.projects_where_can_admin_issues.to_a).to eq([master_project, developer_project, reporter_project])
expect(user.can?(:admin_issue, master_project)).to eq(true)
@@ -1206,10 +1203,8 @@ describe User, models: true do
end
it 'does not include for which the user access level is below reporter' do
- project = create(:project)
- guest_project = create(:project)
-
- guest_project.team << [user, :guest]
+ project = create(:empty_project)
+ guest_project = create(:empty_project) { |p| p.add_guest(user) }
expect(user.projects_where_can_admin_issues.to_a).to be_empty
expect(user.can?(:admin_issue, guest_project)).to eq(false)
@@ -1217,15 +1212,14 @@ describe User, models: true do
end
it 'does not include archived projects' do
- project = create(:project)
- project.update_attributes(archived: true)
+ project = create(:empty_project, :archived)
expect(user.projects_where_can_admin_issues.to_a).to be_empty
expect(user.can?(:admin_issue, project)).to eq(false)
end
it 'does not include projects for which issues are disabled' do
- project = create(:project, issues_access_level: ProjectFeature::DISABLED)
+ project = create(:empty_project, issues_access_level: ProjectFeature::DISABLED)
expect(user.projects_where_can_admin_issues.to_a).to be_empty
expect(user.can?(:admin_issue, project)).to eq(false)
@@ -1241,7 +1235,7 @@ describe User, models: true do
end
context 'without any projects' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
it 'does not load' do
expect(user.ci_authorized_runners).to be_empty
@@ -1250,7 +1244,7 @@ describe User, models: true do
context 'with personal projects runners' do
let(:namespace) { create(:namespace, owner: user) }
- let(:project) { create(:project, namespace: namespace) }
+ let(:project) { create(:empty_project, namespace: namespace) }
it 'loads' do
expect(user.ci_authorized_runners).to contain_exactly(runner)
@@ -1281,7 +1275,7 @@ describe User, models: true do
context 'with groups projects runners' do
let(:group) { create(:group) }
- let(:project) { create(:project, group: group) }
+ let(:project) { create(:empty_project, group: group) }
def add_user(access)
group.add_user(user, access)
@@ -1291,7 +1285,7 @@ describe User, models: true do
end
context 'with other projects runners' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
def add_user(access)
project.team << [user, access]
@@ -1321,8 +1315,8 @@ describe User, models: true do
end
describe '#projects_with_reporter_access_limited_to' do
- let(:project1) { create(:project) }
- let(:project2) { create(:project) }
+ let(:project1) { create(:empty_project) }
+ let(:project2) { create(:empty_project) }
let(:user) { create(:user) }
before do
diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb
index e0368e6001f..72978846e93 100644
--- a/spec/requests/projects/cycle_analytics_events_spec.rb
+++ b/spec/requests/projects/cycle_analytics_events_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe 'cycle analytics events' do
+ include ApiHelpers
+
let(:user) { create(:user) }
let(:project) { create(:project, public_builds: false) }
let(:issue) { create(:issue, project: project, created_at: 2.days.ago) }
@@ -20,19 +22,19 @@ describe 'cycle analytics events' do
it 'lists the issue events' do
get namespace_project_cycle_analytics_issue_path(project.namespace, project, format: :json)
- expect(json_response['events']).not_to be_empty
-
- first_issue_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s
+ first_issue_iid = project.issues.sort(:created_desc).pluck(:iid).first.to_s
+ expect(json_response['events']).not_to be_empty
expect(json_response['events'].first['iid']).to eq(first_issue_iid)
end
it 'lists the plan events' do
get namespace_project_cycle_analytics_plan_path(project.namespace, project, format: :json)
- expect(json_response['events']).not_to be_empty
+ first_mr_short_sha = project.merge_requests.sort(:created_asc).first.commits.first.short_id
- expect(json_response['events'].first['short_sha']).to eq(MergeRequest.last.commits.first.short_id)
+ expect(json_response['events']).not_to be_empty
+ expect(json_response['events'].first['short_sha']).to eq(first_mr_short_sha)
end
it 'lists the code events' do
@@ -40,7 +42,7 @@ describe 'cycle analytics events' do
expect(json_response['events']).not_to be_empty
- first_mr_iid = project.merge_requests.order(id: :desc).pluck(:iid).first.to_s
+ first_mr_iid = project.merge_requests.sort(:created_desc).pluck(:iid).first.to_s
expect(json_response['events'].first['iid']).to eq(first_mr_iid)
end
@@ -49,17 +51,15 @@ describe 'cycle analytics events' do
get namespace_project_cycle_analytics_test_path(project.namespace, project, format: :json)
expect(json_response['events']).not_to be_empty
-
expect(json_response['events'].first['date']).not_to be_empty
end
it 'lists the review events' do
get namespace_project_cycle_analytics_review_path(project.namespace, project, format: :json)
- expect(json_response['events']).not_to be_empty
-
- first_mr_iid = MergeRequest.order(created_at: :desc).pluck(:iid).first.to_s
+ first_mr_iid = project.merge_requests.sort(:created_desc).pluck(:iid).first.to_s
+ expect(json_response['events']).not_to be_empty
expect(json_response['events'].first['iid']).to eq(first_mr_iid)
end
@@ -67,35 +67,32 @@ describe 'cycle analytics events' do
get namespace_project_cycle_analytics_staging_path(project.namespace, project, format: :json)
expect(json_response['events']).not_to be_empty
-
expect(json_response['events'].first['date']).not_to be_empty
end
it 'lists the production events' do
get namespace_project_cycle_analytics_production_path(project.namespace, project, format: :json)
- expect(json_response['events']).not_to be_empty
-
- first_issue_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s
+ first_issue_iid = project.issues.sort(:created_desc).pluck(:iid).first.to_s
+ expect(json_response['events']).not_to be_empty
expect(json_response['events'].first['iid']).to eq(first_issue_iid)
end
context 'specific branch' do
it 'lists the test events' do
- branch = MergeRequest.first.source_branch
+ branch = project.merge_requests.first.source_branch
get namespace_project_cycle_analytics_test_path(project.namespace, project, format: :json, branch: branch)
expect(json_response['events']).not_to be_empty
-
expect(json_response['events'].first['date']).not_to be_empty
end
end
context 'with private project and builds' do
before do
- ProjectMember.first.update(access_level: Gitlab::Access::GUEST)
+ project.members.first.update(access_level: Gitlab::Access::GUEST)
end
it 'does not list the test events' do
@@ -118,10 +115,6 @@ describe 'cycle analytics events' do
end
end
- def json_response
- JSON.parse(response.body)
- end
-
def create_cycle
milestone = create(:milestone, project: project)
issue.update(milestone: milestone)
diff --git a/spec/serializers/pipeline_entity_spec.rb b/spec/serializers/pipeline_entity_spec.rb
index b19464c7117..ccb72973f9c 100644
--- a/spec/serializers/pipeline_entity_spec.rb
+++ b/spec/serializers/pipeline_entity_spec.rb
@@ -134,5 +134,17 @@ describe PipelineEntity do
expect(subject).not_to have_key(:yaml_errors)
end
end
+
+ context 'when pipeline ref is empty' do
+ let(:pipeline) { create(:ci_empty_pipeline) }
+
+ before do
+ allow(pipeline).to receive(:ref).and_return(nil)
+ end
+
+ it 'does not generate branch path' do
+ expect(subject[:ref][:path]).to be_nil
+ end
+ end
end
end
diff --git a/spec/services/ci/update_build_queue_service_spec.rb b/spec/services/ci/update_build_queue_service_spec.rb
new file mode 100644
index 00000000000..f01a388b895
--- /dev/null
+++ b/spec/services/ci/update_build_queue_service_spec.rb
@@ -0,0 +1,47 @@
+require 'spec_helper'
+
+describe Ci::UpdateBuildQueueService, :services do
+ let(:project) { create(:project) }
+ let(:build) { create(:ci_build, pipeline: pipeline) }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+
+ context 'when updating specific runners' do
+ let(:runner) { create(:ci_runner) }
+
+ context 'when there are runner that can pick build' do
+ before { build.project.runners << runner }
+
+ it 'ticks runner queue value' do
+ expect { subject.execute(build) }
+ .to change { runner.ensure_runner_queue_value }
+ end
+ end
+
+ context 'when there are no runners that can pick build' do
+ it 'does not tick runner queue value' do
+ expect { subject.execute(build) }
+ .not_to change { runner.ensure_runner_queue_value }
+ end
+ end
+ end
+
+ context 'when updating shared runners' do
+ let(:runner) { create(:ci_runner, :shared) }
+
+ context 'when there are runner that can pick build' do
+ it 'ticks runner queue value' do
+ expect { subject.execute(build) }
+ .to change { runner.ensure_runner_queue_value }
+ end
+ end
+
+ context 'when there are no runners that can pick build' do
+ before { build.tag_list = [:docker] }
+
+ it 'does not tick runner queue value' do
+ expect { subject.execute(build) }
+ .not_to change { runner.ensure_runner_queue_value }
+ end
+ end
+ end
+end
diff --git a/vendor/gitlab-ci-yml/autodeploy/Kubernetes.gitlab-ci.yml b/vendor/gitlab-ci-yml/autodeploy/Kubernetes.gitlab-ci.yml
new file mode 100644
index 00000000000..36dfc539b3b
--- /dev/null
+++ b/vendor/gitlab-ci-yml/autodeploy/Kubernetes.gitlab-ci.yml
@@ -0,0 +1,76 @@
+# Explaination on the scripts:
+# https://gitlab.com/gitlab-examples/kubernetes-deploy/blob/master/README.md
+image: registry.gitlab.com/gitlab-examples/kubernetes-deploy
+
+variables:
+ # Application deployment domain
+ KUBE_DOMAIN: domain.example.com
+
+stages:
+ - build
+ - test
+ - review
+ - staging
+ - production
+
+build:
+ stage: build
+ script:
+ - command build
+ only:
+ - branches
+
+production:
+ stage: production
+ variables:
+ CI_ENVIRONMENT_URL: http://production.$KUBE_DOMAIN
+ script:
+ - command deploy
+ environment:
+ name: production
+ url: http://production.$KUBE_DOMAIN
+ when: manual
+ only:
+ - master
+
+staging:
+ stage: staging
+ variables:
+ CI_ENVIRONMENT_URL: http://staging.$KUBE_DOMAIN
+ script:
+ - command deploy
+ environment:
+ name: staging
+ url: http://staging.$KUBE_DOMAIN
+ only:
+ - master
+
+review:
+ stage: review
+ variables:
+ CI_ENVIRONMENT_URL: http://$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN
+ script:
+ - command deploy
+ environment:
+ name: review/$CI_BUILD_REF_NAME
+ url: http://$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN
+ on_stop: stop_review
+ only:
+ - branches
+ except:
+ - master
+
+stop_review:
+ stage: review
+ variables:
+ GIT_STRATEGY: none
+ script:
+ - command destroy
+ environment:
+ name: review/$CI_BUILD_REF_NAME
+ action: stop
+ when: manual
+ only:
+ - branches
+ except:
+ - master